마스터 서버(Master Server)

마스터 서버는 클라이언트들을 찾고, 그들을 연결하려는 플레이어 클라이언트들을 찾는 게임들을 위한 만남의 장소입니다. 마스터 서버의 목적은 IP 주소와 포트의 세부사항을 숨기고, 마스터 서버 없이는 불가능한(방화벽 처리, NAT punch-through) 네트워크 연결들을 만드는 기술적인 작업을 수행합니다.

각각의 수행중인 게임 서버는 Game Type을 마스터 서버에게 제공합니다. Game Type이 일치하는 모든 게임들은 함께 모여서 호환되는 클라이언트들이 그들을 쉽게 볼 수 있도록 합니다. 플레이어가 마스터 서버에 접속해서 일치하는 Game Type을 질의할 때, 서버의 유용한 정보들이 플레이어들이 볼 수 있도록 표시됩니다. 이는 플레이어가 어떤 서버로 접속할지 결정하는 것을 돕습니다. 이는 Game Name과 플레이어 카운트, 패스워드가 필요한지 등을 포함합니다. 이 자료를 전송하기 위한 두 개의 함수는 서버를 위한 MasterServer.RegisterHost()이고 플레이어 클라이언트를 위한MasterServer.RequestHostList()입니다.

RegisterHost()를 호출할 때, 세 개의 인자들을 전달할 필요가 있습니다. 이는 등록된 호스트를 위한 gameTypeName (Game Type 지칭), gameName, 그리고 comment 입니다. RequestHostList()는 접속을 하려는 호스트들의 gameTypeName을 인자로 받습니다. 그 타입의 모든 등록된 호스트들은 요청하는 클라이언트들에게 보내어 집니다. 이는 비 동기적 오퍼레이션이며 실제의 호스트 리스트는 도착한 리스트를 리턴하는 PollHostList() 로부터 가져옵니다.

마스터 서버의NAT punchthrough 부분은 실제로 다른 Facilitator라는 개체로부터 수행됩니다. 중앙 유니티 마스터 서버는 게임의 로비가 되고 동시에 Facilitator를 실행시킵니다. 그러므로, 같은 맥락으로 이러한 개념들을 단순히 마스터 서버의 기능들로 간주하셔도 괜찮습니다.

게임을 위해 지정한 Game Type은 게임을 위해서 유일해야 합니다. 이는 완전히 다른 게임을 실행하는 클라이언트들이 서버들을 보고 접속하려는 것을 방지합니다. 그러므로, "Game1"이나 흔한 이름을 gameTypeName으로 쓰지 않길 바랍니다. 특별하고 유니크 한 이름을 쓰길 바랍니다. 만약 다른 버전의 게임을 가지고 있다면, 그 정보를 커멘트 항목에 기입하여 릴레이(중계) 시켜야 합니다. 이를 통하여, 클라이언트들을 그들의 버전이 호스트 리스트의 서버들과 호환되지 않음을 알 수 있습니다. 커멘트 항목은 바라는 다른 정보들을 릴레이 할 수 있습니다. 커멘트 항목은 바이너리 데이터 항목이며, 오브젝트들을 저장 할 수 있습니다. 그러므로, 적절히 사용할 필요가 있습니다.

더 많은 고급 기능들이 커멘트 필드와 마스터 서버 사용자 변형(customizing)을 사용해서 이루어져 정보들을 서버 자신들이 사용할 수 있습니다. 예를 들어, 커멘트 필드의 처음 10바이트들을 패스워드로 보유하고, 호스트 업데이트 수신 시 마스터 서버에서 패스워드를 추출할 수 있습니다. 패스워드와 비교해서 적절하지 않으면, 호스트 업데이트를 거부할 수 있습니다. 물론 이는 마스터 서버의 소스 코드의 편집을 필요로 합니다. 하지만, 이들도 다운로드 되고 편집 될 수 있습니다. 여기에 대한 더 많은 정보는 아래 부분을 건너서 바로 Advanced Section 페이지로 가서 참조하시기 바랍니다.

Registering a game

게임을 등록하기 전에, NAT 기능을 정확하게 설정하는 것은 중요합니다. 설정은 Network.InitializeServer의useNat 인자를 true 또는 false 로 호스트의 네트워킹 기능에 따라 설정합니다. 게임을 호스팅 하는 사용자는 NAT 주소를 가지는지 아닌지를 알아야 하고, 공인 인터넷으로 게임 포트가 접속가능한지를 알아야 합니다. 그러므로, 게임을 호스팅 하기 전에 NAT의 제공이 필요한지 아닌지를 명시해야 합니다.

서버는 아래와 비슷한 코드로 시작합니다:

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");
	}
}

여기서, 머신이 공인 주소를 가지는지 아닌지에 의존해서NAT punchthrough 가 필요한지를 명시해야 합니다. 더 직접적 관련된 함수는Network.TestConnection()이며, 호스트 머신이 NAT를 할 수 있는지 아닌지를 알려줍니다. 이 함수는 게임 포트를 막는지를 알 수 있게 공인 IP주소에 대해 연결 테스트를 합니다. 공인 아이피 주소들을 가지는 머신들은 NAT 테스트를 항상 통과합니다. 만약 실패하면, 호스트는 NAT 클라이언트들에 접속이 _불가능_합니다. 그런 경우, 유저는 게임을 호스팅 하기 위해서는 가능한 포트포워딩(port forwarding)을 설정해야 한다고 고지 받습니다. 일반적으로 저렴한 브로드밴드 접속을 사용하는 사람들은 NAT주소를 가지고, 포트 포워딩을 설정할 수 없습니다(그들은 주로 개인의 공인 IP 주소도 없습니다). 이런 경우에는, NAT 테스트가 실패하면, 사용자는 같은 로컬 네트워크에 있는 클라이언트를 제외하고는 접속이 불가능하므로 서버를 실행하는 것이 추천되지 않는다고 고지 받습니다.

호스트가 NAT기능들을 필요로 하지 않는데 사용가능 시켜도, 아무런 해가 없으면 여전히 접속 가능합니다. 그러나, NAT punchthrough 를 할 수 없는 클라이언트들은 호스트의 접속불가를 호스트의NAT 사용기능이라고 생각할 것입니다.

게임에 접속

호스트 정보, HostData, 호스트 등록시 또는 질의시에 보내어지는 오브젝트는 다음의 정보를 포함합니다:

boolean useNat
String gameType
String gameName
int connectedPlayers
int playerLimit
String[] IP
int port
boolean passwordProtected
String comment
String guid

이 정보는 호스트들의 접속 능력을 알기 위해서 클라이언트에 의해 사용되는 정보입니다. NAT가 사용가능 할 때, 접속 시 호스트의 GUID를 사용할 필요가 있습니다. HostData 구조체에 접속할 때 자동으로 처리됩니다. 접속 루틴은 아래와 같습니다:

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();	
	}
}

이 예제 코드는 마스터 서버에 의해 리턴 되는 호스트들의 모든 상응하는 정보를 프린트합니다. 핑 정보나 호스트의 지리적 위치와 같은 다른 유용한 데이터도 여기에 추가될 수 있습니다.

NAT punchthrough

NAT punchthrough는 모든 시간에 100% 작동하지 않는다는 점을 명심하십시오. 그러므로, 몇몇 클라이언트들은 접속하고, 다른 클라이언트들은 NAT 서버에 접속이 힘들 수 있으므로, 특정 머신들은 서버로 실행되기에 적합하지 않습니다.

기본적으로, NAT punchthrough 는 마스터 서버의 도움으로 수행되지만, 이 마스터 서버에 의존할 필요가 없습니다. Facilitator가 사실 NAT punchthrough 루틴을 위해 사용됩니다. 두 머신들이Facilitator 에 접속하고, 외부 IP주소와 포트가 있다면, 한 머신은 다른 머신에 직접 접속합니다. 마스터 서버는 이 외부 IP주소와 포트 정보를 제공하는데 사용하는데, 마스터 서버가 없다면 이러한 정보들은 알아내기 쉽지 않습니다. 이것이 왜 마스터 서버와Facilitator 가 밀접하게 결합된 이유입니다. 마스터 서버와Facilitator는 기본적으로 같은 IP주소를 가집니다. 둘 중 하나를 바꾸시려면 MasterServer.ipAddress, MasterServer.port, Network.natFacilitatorIP, Network.natFacilitatorPort를 사용하십시오

advanced

고급(Advanced)

마스터 서버는 유니티 에디터 자신으로부터 완전히 분리된 개체입니다. 윈도우, 리눅스와 맥 OS에 배치(deploy)될 수 있으며, 누구나 자신의 마스터 서버를 가질 수 있습니다. 유니티 기술들은 모두에게 사용 가능한, 사용되는 디폴트 서버인, 전속 마스터 서버를 가집니다.

마스터 서버가 어떻게 정보를 다루고 통신하는지 변경을 원하는 경우가 있습니다. 또는, 개개의 게임 서버로부터 어떻게 마스터 서버가 호스트 데이터 정보를 다루는지 최적화 해야 할 필요가 있습니다. 또는, 클라이언트들이 호스트 리스트를 (숫자로 또는 필터와 같은 지역 등의 종류로)요구할 때 얼마나 많은 호스트를 받을 지의 한계를 정해야 할 필요가 있습니다. 이는 대게 대역폭 최적화인데, 유니티 플레이어와 정상적으로 통신할 수 있는 한 어떠한 일들도 가능합니다.

이러한 변경을 수행하기 위해서는, 자신의 마스터 서버를 수정, 빌드, 배치해야 합니다. 이 기능에 관한 정보는 Master Server Build page에서 찾으실 수 있습니다.

역링크