[Unity Server] # 2 - TCP Server/Client 통신

qweasfjbv·2025년 2월 6일

UnityServer

목록 보기
2/9

개요


포트포워딩이 제대로 된 것을 확인했으니, 클라이언트와 서버를 각각 빌드하여 통신이 제대로 되는지 확인해야 합니다. 그러기 위해서, 우선 간단한 통신을 할 수 있는 코드를 짜보겠습니다.

구현


Client


	public class ClientManager
	{
    
		public void SendMessage()
		{
			_ = Task.Run(() => SendMessageAsync());
		}
		int number = 0;
		private async void SendMessageAsync()
		{
			TcpClient client = new TcpClient(Constants.IP_ADDR_INHO, Constants.PORT_VM_TCP);
			NetworkStream stream = client.GetStream();

			string data = "HELLO SERVER!" + number++;
			byte[] buffer = Encoding.UTF8.GetBytes(data);
			await stream.WriteAsync(buffer, 0, buffer.Length);
			await stream.FlushAsync();

			buffer = new byte[1024];
			int bytesRead = stream.Read(buffer, 0, buffer.Length);
			string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
			Debug.Log("RESPONSE : " + response);

			client.Close();
		}

간단하게 string을 주고 받는 클라이언트입니다.
TCP 통신은 byte stream으로 이루어지기 때문에, 더 복잡한 데이터를 주고받기 위해서는 직렬화 과정이 필요합니다.

Server


	public class ServerManager : MonoBehaviour
	{
    	//
        //	other funcs...
        //

		
		private async void StartServer()
		{
			TcpListener listener = new TcpListener(IPAddress.Any, Constants.PORT_VM_TCP);
			listener.Start();
			
			while (true)
			{
				TcpClient client = await listener.AcceptTcpClientAsync();
				DebugServer.Log("ClientConnected");

				_ = Task.Run(() => HandleClient(client));
			}
		}

		private async void HandleClient(TcpClient client)
		{
			try
			{
				byte[] buffer = new byte[1024];
				int bytesRead;
				Stream stream = client.GetStream();

				while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
				{
					string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
					DebugServer.Log("Received: " + data);

					string result = await RunSimulation();
					byte[] sendBuff = Encoding.UTF8.GetBytes(result);
					await stream.WriteAsync(sendBuff, 0, sendBuff.Length);
					DebugServer.Log("Transmit: " + result);
				}
			}
			catch(Exception ex)
			{
				DebugServer.Log($"Client Error : {ex.Message}");
			}
			finally
			{
				client.Close();
			}
		}

		private async Task<String> RunSimulation()
		{
			await Task.Delay(4000);         // HACK - 4초 딜레이
			return "Hello Client!";
		}
	}

Server도 간단한 Iterative Echo Server 입니다.
저는 Headless 로 Simulation을 돌리는게 목적이기 때문에 RunSimulation 함수에서 4초 정도의 딜레이를 주고 테스트 해보았습니다.

빌드 및 테스트

새로운 씬을 만들고, StartServer 를 호출하게 만든 후에 빌드를 진행했습니다.
해당 빌드파일은 VMWare 의 SharedFolder 기능을 사용하여 전송했습니다.

비동기적으로 잘 처리되는 모습을 확인하실 수 있습니다.

마무리


간단한 string을 서버에서 비동기적으로 처리하여 여러 요청을 동시에 받을 수 있도록 해보았습니다.
이제 보내는 데이터를 구조체로 바꾸고 직렬화하여 바이트 스트림으로 보낼 수 있도록 하겠습니다.

0개의 댓글