카테고리 없음

TcpListener와 TcpClient를 써봤다.

hyuckkim 2021. 8. 22. 22:38

Socket 형식으로 어떻게 어떻게 하는 것보다 더 비용이 비싸지만 훨씬 간편하다.

 

서버쪽에서는 TcpListener, 클라이언트 쪽에서는 TcpClient를 사용한다.

 

여러 컴퓨터 간에 통신이 아니라 내 컴퓨터 안에서의 프로그램 간에 통신이라서 남이 보면 많이 싱거울 수 있겠다.

 

 

 

서버 측에서 해야 하는 일은 다음과 같다 : 

public static void Listen()
{
  int port = 13000;
  IPAddress localaddr = IPAddress.Parse("127.0.0.1");

  server = new TcpListener(localaddr, port);
  server.Start();

  connect = server.AcceptTcpClientAsync();
}

1. 서버를 열어야 한다.

AcceptTcpClientAsync()로 비동기적으로 연결을 받을 수 있다.

connect는 Task<TcpClient> 다른 TcpClient가 접속하면 그 클라이언트를 Result로 얻는다.

if (TcpServer.connect is not null && TcpServer.connect.IsCompleted)
{
  console.Content = "연결됨!";
  TcpServer.SendToClient(pos.X + "," + pos.Y);
}

Task이므로 connect.IsCompleted 상태가 되면 연결되었다는 뜻이다

DispatcherTimer 반복에서 연결을 확인했다. WPF 에서 타이머 사용하기 :: 개발하는곰의 개발노트 (tistory.com)

 

public static void SendToClient(string str)
{
  NetworkStream stream = client.GetStream();

  byte[] msg = Encoding.ASCII.GetBytes(str);
  stream.Write(msg, 0, msg.Length);
  task = stream.ReadAsync(buffer);
}

2. 클라이언트에 메시지를 보낸다.

stream.getStream으로 메시지를 보낼 수 있는 영역을 얻어서 거기에 Write 하면 된다.

다시 stream.ReadAsync로 다음 메시지를 받을 준비를 하자.

if (TcpServer.task is not null && (TcpServer.task?.IsCompleted ?? false))
{
  string result = Encoding.ASCII.GetString(TcpServer.buffer);
  console.Content = result;
  TcpServer.task = null;
  TcpServer.SendToClient(pos.X + "," + pos.Y + '\0');
}

task.isCompleted라면 값이 있는 것이다. 

task의 자료형을 ValueTask<int>?로 해두고 일이 없을 때에는 null로 채워 두었다.

ValueTask는 한 번만 써야 한다는 경고가 발생하지만 한 번만 쓸 거니까 괜찮다.

 

클라이언트 측에서 해야 할 일은 다음과 같다 : 

public static void Connect()
{
  string server = "127.0.0.1";
  int port = 13000;
  client = new TcpClient(server, port);
  stream = client.GetStream();
  task = stream.ReadAsync(buffer);
}

서버에 연결한다. stream을 자기 자신에게서 가져온다는 것만 빼면 완전히 같다.

TcpClient(server, port)를 사용하면 그 서버 그 포트에 자동으로 연결하며 생성된다.

public static void SendToServer(string str)
{
  byte[] msg = Encoding.ASCII.GetBytes(str);

  stream.Write(msg, 0, msg.Length);
  task = stream.ReadAsync(buffer);
}

그리고 서버해서 하던 거 그대로.

 

 

TcpListener 클래스 (System.Net.Sockets) | Microsoft Docs

 

TcpListener 클래스 (System.Net.Sockets)

TCP 네트워크 클라이언트에서 연결을 수신합니다.Listens for connections from TCP network clients.

docs.microsoft.com

 

마이크로소프트가 참 좋은게, 공식 문서가 다 있다. 

 

 

결과 : 

 

끝.

 

 

10-04 수정

https://github.com/hyuckkim/TcpCouple 

 

GitHub - hyuckkim/TcpCouple: TcpListener를 이용해 local에서 창끼리 서로 가리키도록 하는 WPF 앱입니다.

TcpListener를 이용해 local에서 창끼리 서로 가리키도록 하는 WPF 앱입니다. - GitHub - hyuckkim/TcpCouple: TcpListener를 이용해 local에서 창끼리 서로 가리키도록 하는 WPF 앱입니다.

github.com