Version: 2017.4
네트워크 레벨 로드(레거시)
자신만의 Unity 네트워킹 서버 구축(레거시)

마스터 서버(레거시)

(새 프로젝트에는 5.1에서 도입된 새로운 네트워킹 시스템을 사용해야 합니다. 다음 내용은 이전 네트워킹 시스템을 사용하는 레거시 프로젝트를 대상으로 작성되었습니다.)

마스터 서버는 플레이어 클라이언트가 게임 인스턴스에 연결하기 위한 만남의 장소입니다. 포트 번호와 IP 주소를 숨길 수 있으며 방화벽 다루기 또는 NAT 펀치스루 등 네트워크 연결을 설정할 때 발생할 수 있는 기술적인 태스크를 수행합니다.

실행 중인 각 게임 인스턴스는 마스터 서버에 Game Type 을 제공합니다. 플레이어가 마스터 서버에 연결하고 Game Type 이 일치하는지 쿼리하면 서버에서는 실행 중인 게임 수와 각각의 플레이어 수, 그리고 플레이에 대한 암호 필요 여부를 응답합니다. 데이터 교환을 위한 두 가지 함수는 서버용 MasterServer.RegisterHost()와 플레이어 클라이언트용 MasterServer.RequestHostList()입니다.

RegisterHost 를 호출할 때 gameTypeName(이전의 Game Type), gameName, comment 등 세 개의 인수를 전달해야 합니다. RequestHostList 는 연결하려는 호스트의 gameTypeName 을 인수로 이용합니다. 그 타입에 등록되어 있는 호스트가 요청 클라이언트에 반환됩니다. 이것은 비동기 처리이며 완전히 송신한 후에 PollHostList() 를 통해 전체 리스트를 받을 수 있습니다.

마스터 서버에 의한 NAT 펀치스루 의무는 Facilitator 라는 별도의 프로세스에 의해 처리되지만 Unity의 마스터 서버는 두 서비스를 병렬 처리합니다.

Game Type 은 각각의 게임을 고유하게 식별하는 이름이어야 합니다(그러나 Unity는 이를 보장하는 중앙 등록 시스템은 가지고 있지 않습니다). 다른 곳에서 사용되고 있지 않은 독자적인 이름을 선택합니다. 만약 게임에 다른 버전이 있는 경우에는 사용자에게 경고를 하여 클라이언트가 실행 중인 서버의 버전과 호환되지 않는다는 것을 알려야 합니다. 버전 정보는 코멘트 필드에 전달합니다(바이너리 데이터이므로 버전은 원하는 형식으로 전달할 수 있습니다). 게임의 이름은 단순히 설정한 사람이 제공한 특정 게임 인스턴스의 이름입니다.

코멘트 필드는 마스터 서버를 적절히 설정하면 더 진보된 방법으로 사용할 수 있습니다(이에 대한 자세한 내용은 고급 섹션을 참조하십시오). 예를 들어, 코멘트의 처음 10바이트를 암호로 남겨둔 후 마스터 서버에서 호스트 업데이트를 수신했을 때 암호를 풀 수 있습니다. 암호 확인에 실패할 경우 호스트 업데이트를 리젝트할 수 있습니다.

게임 등록

게임 등록 전에 호스트에서 지원하는지에 따라 NAT 기능을 활성화·또는 비활성화 하는 것이 중요합니다. 이것은 Network.InitializeServeruseNat 파라미터를 통해 시행할 수 있습니다.

서버는 다음과 비슷한 코드로 시작될 수 있습니다.

using UnityEngine;
using UnityEngine.Network;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    void OnGUI() {
        if (GUILayout.Button ("Start Server"))
        {
            // Use NAT punchthrough if no public IP present
            Network.InitializeServer(32, 25002, !Network.HavePublicAddress());
            MasterServer.RegisterHost("MyUniqueGameType", "JohnDoes game", "l33t game for all");
        }
    }
}

C# 스크립트 예제

function OnGUI() {
    if (GUILayout.Button ("Start Server"))
    {
        // Use NAT punchthrough if no public IP present
        Network.InitializeServer(32, 25002, !Network.HavePublicAddress());
        MasterServer.RegisterHost("MyUniqueGameType", "JohnDoes game", "l33t game for all");
    }
}

JS 스크립트 예제

여기에서는 NAT 펀치스루가 필요한지 여부를 컴퓨터에 공용 IP 주소가 있는지 확인하여 결정합니다. Network.TestConnection 함수는 보다 정교한 함수로서 호스트 시스템이 NAT를 할 수 있는지 판단할 수 있습니다. 또한 공용 IP 주소에 대해 연결 테스트를 하여 게임 포트를 방화벽이 차단하고 있는지 확인합니다. 공용 IP 주소가 있는 컴퓨터는 항상 NAT 테스트를 통과하지만, 연결 테스트에 실패하면 호스트는 NAT 클라이언트에 연결할 수 없습니다. 그런 경우에 게임을 작동시키려면 포트 포워딩이 필요하다는 것을 사용자에게 알려줘야 합니다. 로컬 광대역 연결은 일반적으로 NAT 주소가 있지만, 포트 포워딩을 설정할 수 없습니다(공용 IP 주소가 없기 때문). 이러한 경우 NAT 테스트가 실패하면 로컬 네트워크의 클라이언트만 연결할 수 있기 때문에 서버 실행이 권장되지 않는다는 것을 사용자에게 알려야 합니다.

호스트가 NAT 기능을 필요로 하지 않는데 활성화한 경우에도 이 기능을 사용할 수 있습니다. 그러나 NAT 펀치스루를 할 수 없는 클라이언트는 서버에서 NAT가 활성화되었기 때문에 연결할 수 없다고 오해할 가능성이 있습니다.

게임 연결

HostData 오브젝트는 호스트 등록 또는 쿼리 중일 때 전송됩니다. 다음 호스트에 대한 정보를 보유하고 있습니다.

boolean useNat 호스트가 NAT 펀치스루를 사용하는지 표시합니다.
String gameType 호스트의 게임 타입입니다.
String gameName 호스트의 게임 이름입니다.
int connectedPlayers 현재 연결된 플레이어/클라이언트의 수입니다.
int playerLimit 동시 접속할 수 있는 최대 플레이어/클라이언트 수입니다.
String[] IP 호스트의 내부 IP 주소입니다. 공용 주소를 가진 서버에서는 외부와 내부 주소가 동일합니다. 내부 연결하는 경우 모든 IP 주소와 컴퓨터의 모든 인터페이스를 연결해서 확인해야 하기 때문에 필드는 배열로 정의되어 있습니다.
int port 호스트의 포트입니다.
boolean passwordProtected 호스트 연결에 암호가 필요한지 여부를 지정합니다.
String comment 호스트 등록시 설정된 코멘트입니다.
String guid 호스트의 네트워크 GUID입니다. NAT 펀치스루에 연결하는 데 필요합니다.

이 정보는 클라이언트가 호스트가 연결할 수 있는지 보기 위해 사용됩니다. NAT가 활성화된 경우 연결할 때 호스트의 GUID가 필요합니다. 이것은 연결할 때 HostData 가 수신되었을 때 자동으로 처리됩니다. 연결 루틴은 다음과 같이 됩니다.

using UnityEngine;
using UnityEngine.Network;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    void Awake() {
        MasterServer.RequestHostList("MadBubbleSmashGame");
    }
    
    void OnGUI() {
        HostData[] data = MasterServer.PollHostList();
        // Go through all the hosts in the host list
        foreach (var element in data)
        {
            GUILayout.BeginHorizontal();    
            var name = element.gameName + " " + element.connectedPlayers + " / " + element.playerLimit;
            GUILayout.Label(name);  
            GUILayout.Space(5);
            string hostInfo;
            hostInfo = "[";
            foreach (var host in element.ip)
                hostInfo = hostInfo + host + ":" + element.port + " ";
            hostInfo = hostInfo + "]";
            GUILayout.Label(hostInfo);  
            GUILayout.Space(5);
            GUILayout.Label(element.comment);
            GUILayout.Space(5);
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Connect"))
            {
                // Connect to HostData struct, internally the correct method is used (GUID when using NAT).
                Network.Connect(element);           
            }
            GUILayout.EndHorizontal();  
        }
    }
}

C# 스크립트 예제

function Awake() {
    MasterServer.RequestHostList("MadBubbleSmashGame");
}

function OnGUI() {
    var data : HostData[] = MasterServer.PollHostList();
    // Go through all the hosts in the host list
    for (var element in data)
    {
        GUILayout.BeginHorizontal();    
        var name = element.gameName + " " + element.connectedPlayers + " / " + element.playerLimit;
        GUILayout.Label(name);  
        GUILayout.Space(5);
        var hostInfo;
        hostInfo = "[";
        for (var host in element.ip)
            hostInfo = hostInfo + host + ":" + element.port + " ";
        hostInfo = hostInfo + "]";
        GUILayout.Label(hostInfo);  
        GUILayout.Space(5);
        GUILayout.Label(element.comment);
        GUILayout.Space(5);
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Connect"))
        {
            // Connect to HostData struct, internally the correct method is used (GUID when using NAT).
            Network.Connect(element);           
        }
        GUILayout.EndHorizontal();  
    }
}

JS 스크립트 예제

이 예제에서는 마스터 서버에서 반환하는 모든 관련 호스트 정보가 출력됩니다. ping 정보와 호스트의 지리 정보와 같은 유용한 정보도 여기에 추가할 수 있습니다.

NAT 펀치스루

NAT 펀치스루가 가능한가에 따라 특정 컴퓨터가 서버로서 적합한지 보여줍니다. 일부 클라이언트를 연결할 수 있지만 NAT 서버에 연결하는 데 문제가 있는 클라이언트가 나올 수 있습니다.

기본적으로 NAT 펀치스루는 마스터 서버의 협력에 의해 제공되지만 반드시 이 방법이 아니어도 됩니다. 퍼실리테이터는 NAT 펀치스루 서비스에 실제로 사용되는 프로세스입니다. 두 컴퓨터가 퍼실리테이터에 연결되어 있는 경우 외부 IP 주소와 포트가 사용되는 한 모두 서로 연결할 수 있는 것처럼 보입니다. 마스터 서버는 다른 방법으로는 판단하기 어려운 외부 IP와 포트 정보를 제공하는 데 사용됩니다. 마스터 서버와 퍼실리테이터가 밀접하게 통합되어 있는 것은 이 때문입니다. 마스터 서버와 퍼실리테이터는 기본적으로 동일한 IP 주소를 가지며 이 중 하나를 변경하려면 MasterServer.ipAddress, MasterServer.port, Network.natFacilitatorIPNetwork.natFacilitatorPort를 사용합니다.

고급

Unity Technologies에는 테스트 목적으로 완전히 배포된 마스터 서버가 있으며 이 서버는 실제로 디폴트 서버로서 사용됩니다. 그러나 소스 코드는 무료로 제공되고 있으며 Windows, Linux 및 Mac OS에서 사용 가능합니다. 프로젝트를 소스에서 빌드하는 방법 이외에 마스터 서버가 정보의 처리 방법 및 통신 방식을 수정하고 싶은 경우가 있을지도 모릅니다. 예를 들어, 호스트 데이터 처리를 최적화하거나 호스트 리스트에 반환되는 클라이언트의 수를 제한할 수 있습니다. 이러한 변경은 소스 코드의 변경을 동반하며 이 방법에 대한 자세한 내용은 마스터 서버 빌드 페이지를 참조하십시오.

네트워크 레벨 로드(레거시)
자신만의 Unity 네트워킹 서버 구축(레거시)