본문 바로가기
wpf/c#, wpf 채팅프로그램

c# 채팅프로그램 만들기 - 2 - 소켓통신(TcpListener, TcpClient)을 이용한 간단한 1:1 통신을 해보자(동기서버, 클라이언트, 지속성)

by devjh 2020. 7. 13.
반응형

채팅프로그램 만들기는 총 12개의 게시글로 구성되어있습니다.

 

첫번째 게시글 : 1:1단발성통신(동기서버 동기클라)

 

두번째 게시글 : 1:1지속성통신(동기서버 완성본 동기 클라이언트)

 

세번째 게시글 : 1:1통신(비동기서버)

 

네번째 게시글: 1:N통신(여기서부터는 여러명을 받아야하므로 당연히 비동기서버입니다.)

 

다섯번째 게시글 : 채팅프로그램 콘솔 서버

 

여섯번째 게시글 : 채팅프로그램 콘솔 클라이언트

 

일곱번째 게시글 : wpf를 통해 View를 구현한 서버

 

여덟번째 게시글 : wpf를 통해 View를 구현한 클라이언트(메인화면 만들기)

 

아홉번째 게시글 : wpf를 통해 View를 구현한 클라이언트(로그인화면 만들기)

 

열번째 게시글 : wpf를 통해 View를 구현한 클라이언트(채팅상대 선택화면 만들기)

 

열한번째 게시글 : wpf를 통해 View를 구현한 클라이언트(채팅화면 만들기)

 

열두번째 게시글 : wpf를 통해 View를 구현한 클라이언트(로직 구현)

 


 

저번 게시글에서는 1:1통신을 통해 서버는 message를 기다리고 message가 오면 출력해준후 프로그램을 종료시키는 1:1 단발형 통신프로그램을 만들어봤습니다.

 

이번 게시글에서는 서버는 client의 message를 기다리고 message가 왔다면 출력, 다시 message를 기다리는 방식의 지속성의 서버와 계속해서 메시지를 보낼 수 있는 클라이언트를 만들어보겠습니다.

 

서버와 클라이언트 모두 콘솔창으로 만들 예정이며 기본적인 콘솔 로직은 아래의 방법을 사용할 예정입니다.

 

아래코드가 이해가 되지 않는분은 해당코드를 한번 돌려보세요.

while (true)
{
	Console.WriteLine("이름을 입력하세요");
	string name = Console.ReadLine();

	Console.WriteLine("당신의 이름은 {0} 입니다.",name);

	Console.ReadKey();
	Console.Clear();
}

 

1. 서버

서버는 저번게시글의 서버와 크게 다르지 않습니다.

 

다른점은 저번서버는 client가 보낸 message를 한번 읽고 콘솔에 출력후 프로그램이 종료되었다면

 

이번서버는 출력후 다시 읽을준비를 하는 서버입니다.

 

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("서버콘솔창. \n");

        // TcpListener 생성자에 붙는 매개변수는 
        // 첫번째는 IP를 두번째는 port 번호입니다.
        TcpListener server = new TcpListener(IPAddress.Any, 9999);

        // 서버를 시작합니다.
        server.Start();

        // 클라이언트 객체를 만들어 9999에 연결한 client를 받아옵니다
        // 받아올때까지 서버는 대기합니다.
        TcpClient client = server.AcceptTcpClient();
        Console.WriteLine("클라이언트가 접속하였습니다");

        // 한번 읽고 콘솔창 출력이 완료된 후 다시 while루프를 읽을 데이터를 기다립니다.
        while (true)
        {
            // Socket은 byte[] 형식으로 데이터를 주고받으므로 byte[]형 변수를 선언합니다.
            byte[] byteData = new byte[1024];
            // client가 write한 정보를 읽어옵니다.
            // 아래의 작업 이후에 byteData에는 읽어온 데이터가 들어갑니다.
            client.GetStream().Read(byteData, 0, byteData.Length);

            // 출력을 위해 string형으로 바꿔줍니다.
            string strData = Encoding.Default.GetString(byteData);

            // byteData의 크기는 1024인데 스트림에서 읽어온 데이터가 1024보다 작은경우
            // 공백이 출력되니 비어있는 문자열을 제거합니다.
            int endPoint = strData.IndexOf('\0');
            string parsedMessage = strData.Substring(0, endPoint + 1);

            // 파싱된 데이터를 출력해주고 while루프를 돕니다.
            Console.WriteLine(parsedMessage);
        }
    }
}

 

2. 클라이언트

while문을 통해 message를 계속 보낼 수 있다는것과

 

int.tryparse 및 console.clear(), console.readkey()가 추가되어

 

사용자와의 인터페이스가 구성된것 외에는 저번게시글과 크게 다르지 않습니다.

 

class MyContinuousClient
{
    TcpClient client = null;
    public void Run()
    {
        while (true)
        {
            Console.WriteLine("==========클라이언트==========");
            Console.WriteLine("1.서버연결");
            Console.WriteLine("2.Message 보내기");
            Console.WriteLine("==============================");

            string key = Console.ReadLine();
            int order = 0;

            // 입력받은 key의 값을 int.TryParse를 사용해 int형으로 형변환해줍니다.
            // 형변환에 성공하면 order에 변환된 값이 저장됩니다.
            // 형변환에 실패하면 false를 리턴합니다.
            if (int.TryParse(key, out order))
            {
                switch(order)
                {
                    case 1:
                    {
                        if (client != null)
                        {
                            Console.WriteLine("이미 연결되어있습니다.");
                            Console.ReadKey();
                        }
                        else
                        {
                        	Connect();
                        }

                        break;
                    }
                    case 2:
                    {
                        if (client == null)
                        {
                            Console.WriteLine("먼저 서버와 연결해주세요");
                            Console.ReadKey();
                        }
                        else
                        {
                        	SendMessage();
                        }
                        break;
                    }
                }
            }

            else
            {
                Console.WriteLine("잘못 입력하셨습니다.");
                Console.ReadKey();
            }
            Console.Clear();
        }
    }

    private void SendMessage()
    {
        // 이전게시물에서 다룬 내용이니 따로 다루지 않겠습니다.
        Console.WriteLine("보낼 message를 입력해주세요");
        string message = Console.ReadLine();
        byte[] byteData = new byte[message.Length];
        byteData = Encoding.Default.GetBytes(message);

        client.GetStream().Write(byteData, 0, byteData.Length);
        Console.WriteLine("전송성공");
        Console.ReadKey();
    }


    private void Connect()
    {
        // 이전게시물에서 다룬 내용이니 따로 다루지 않겠습니다.
        client = new TcpClient();
        client.Connect("127.0.0.1", 9999);
        Console.WriteLine("서버연결 성공 이제 Message를 입력해주세요");
        Console.ReadKey();
    }
}

 

3. 결과

 

 

반응형

댓글