네트워크/채팅 프로그램

[TCP/IP 소켓 프로그래밍] Winform 을 이용한 채팅 프로그램 - 3

차나히 2023. 10. 25. 22:15

각 클라이언트에서 작성한 메시지를 서버로 보내보는 작업까지 완료해보았다. 이제 조금 더 채팅 프로그램 스럽게 만들 수 있도록 각 클라이언트에서 보낸 메시지를 채팅 창에 띄워주는 작업을 해보자. 

 

서버에서 클라이언트로 메시지 보내기

클라이언트에서 TcpClient 와 NetworkStream 을 이용해서 서버로 메시지를 전송했듯, 서버에서도 마찬가지로 메시지를 클라이언트 단으로 넘겨줄 수 있다. 그러면 일단 서버에서 클라이언트로 메시지를 넘기는 작업을 해보자.

 

public static void RecvMsgFromClient(CLIENT_TYPE ClientType)
{
    while (true)
    {
        byte[] Buff = new byte[1024];
        int Nbytes;
        string ReceiveData = "";

        if(ClientType == CLIENT_TYPE.FIRST)
        {
            while ((Nbytes = FirstClientStream.Read(Buff, 0, Buff.Length)) > 0)
            {
                ReceiveData = Encoding.Unicode.GetString(Buff, 0, Nbytes);

                Console.WriteLine("1번 클라이언트 : " + ReceiveData);
                SendMsgToClient(SecondClientStream, Buff);
            }
        }
        if(ClientType == CLIENT_TYPE.SECOND) 
        {
            while ((Nbytes = SecondClientStream.Read(Buff, 0, Buff.Length)) > 0)
            {
                ReceiveData = Encoding.Unicode.GetString(Buff, 0, Nbytes);

                Console.WriteLine("2번 클라이언트 : " + ReceiveData);
                SendMsgToClient(FirstClientStream, Buff);
            }
        }                
    }
}

public static void SendMsgToClient(NetworkStream Stream, byte[] Msg)
{
    Stream.Write(Msg);

    Stream.Flush();
}

 

 

기존에 서버로 메시지를 보내는 테스트에서 작성했던 코드에서 약간 수정이 필요하다. 기존에는 메시지를 서버로 보내기만 하면 됐기 때문에 단순하게 Client 의 Type 만 체크한 뒤, 서버 콘솔 쪽에 메시지를 띄워주었다.

 

다만, 이제는 1번 클라이언트에서 받아온 메시지를 2번 클라이언트로 넘겨주어야 한다. 이 과정에서 1번 클라이언트의 Stream 과 2번 클라이언트의 Stream 을 구분해주어야 할 필요성이 생겼다. 그래서 각 Stream 을 전역변수로 설정해주고, 1번 클라이언트에서 메시지를 받을 때는 1번 클라이언트에 연결된 Stream 을, 받아온 메시지를 2번 클라이언트에 넘겨줄때는 2번 클라이언트에 연결된 Stream 을 사용했다. 

 

Stream 을 잘 구분해 준 뒤, 이 Stream 을 이용해서 Write() 함수를 호출하면 서버에서 클라이언트로 메시지를 보내줄 수 있다. 

 

클라이언트에서 메시지 받기

 

서버에서 보내준 메시지를 이제 클라이언트 단에서 받아보자. 이 과정에서는 각 클라이언트에 하나의 Thread 를 추가한 뒤, Thread 가 하는 작업으로는 메시지를 받는 작업을 추가해주면 될것같다. 이 부분은 사실 서버에서 메시지를 받는 로직을 참고하면 좋다. 받아온 메시지는 일단 테스트용으로 바로 TextBox 에 추가해서 메시지가 잘 도착했는지 확인만 해보자. 

 

private void RecvMsg()
{
    while (true)
    {
        if (Stream == null)
        {
            continue;
        }

        byte[] Buff = new byte[1024];
        int Nbytes;
        string ReceiveData = "";


        while ((Nbytes = Stream.Read(Buff, 0, Buff.Length)) > 0)
        {
            ReceiveData = Encoding.Unicode.GetString(Buff, 0, Nbytes);
            BeginInvoke(new Action(() =>
            {
                // UI 작업은 여기에서 수행됩니다.
                textBox_RecvMsg.Text = ReceiveData;
            }));
        }
    }
}

 

 

RecvMsg() 함수는 별도의 Thread 를 하나 생성해주고, 클라이언트쪽 Form 이 생성될 때 실행되는 함수다. 이를 이용해서 서버에서 보내지는 메시지를 가져올 수 있으며, 가져온 메시지를 이용해서 UI 에 뿌려줄 수 있다. 단, Thread 내에서 UI 를 변경하는것은 허용되지 않기 때문에 BeginInvoke 함수를 이용해서 UI 변경을 처리해주면 완료. 아래와 같은 결과가 나오게 된다. 

 

 

메시지 잘 도착

 

 

메시지를 잘 받아봤으니, 이제 받아온 메시지를 UI 상에 이쁘게 꾸며주기만 하면 좋을것같다. 다음번에는 채팅 UI 를 추가해서 진짜 채팅처럼 만들어보자.