• C# 소켓, 스레드를 이용한 채팅 프로그램

    2020. 1. 7.

    by. 안녕진

    (C#을 처음 시작했기 때문에, 틀리거나 비효율적인 부분이 많이 있을 수 있습니다. 알려주시면 수정하겠습니다.)

     

     

    C#이 Java와 너무 비슷해서, Java로 배운 네트워크/스레드 프로그래밍 기술(?)로 만든 엄청 간단한 채팅 프로그램이다.

    Socket 통신에 관한 내용은 다른 블로그들에 너무너무 설명이 잘 돼있으니 참고하자!

     

     

    작동 방식은 아래와 같다.

    1. A, B, C 접속

    2. A가 메시지를 보냄 => 서버에 전송 => 서버가 B, C에게 A의 메시지를 보냄

    ** 클라이언트끼리의 통신이 아니고, 클라이언트들과 서버의 통신이다.

     

     

    테스트방법(사용방법)은

    1. 서버프로그램과 클라이언트(2~3개)프로그램들을 차례대로 실행한다.(서버부터 실행)

    **실행 == dotnet run

    2. 모든 클라이언트 프로그램에 id/client1 처럼 아이디(client1)를 입력한다. (아이디는 서로 다르게)

    3. 한 클라이언트 프로그램에 addMsg/입력할메시지 라고 입력하고, 다른 프로그램들의 변화를 관찰한다.

    왼쪽부터 순서대로 서버 / 클라이언트1 / 클라이언트2

     

     

    client와 server 모두 아래와 비슷하게 while문을 돌며 각각 server측 / client측의 입력을 계속 받도록 했고,

    외부(server 혹은 client)로부터 입력을 받을 때, 다른 작업(server 혹은 client로의 전송)을 할 수 있도록 Thread를 생성하여 실행했다.

    아래는 client의 source code 중 일부이다.

    (new Thread(new ThreadStart(() =>
                {
                    while(true)
                    {
                        String line = "";
                        while(line.Equals(""))
                        {
                            line = reader.ReadLine();
                            if(line == null)
                            {
                                Console.WriteLine("서버와의 연결이 끊어졌습니다.");
                                return;
                            }
                        }
                        String[] command = line.Split("/");
                        if(command[0].Equals("addMsg"))
                        {
                            Console.WriteLine(command[1] + "/" + command[2]);
                        }
                    }
                }))).Start();

     

     

    아래는 전체 source code이다.

     

    Server

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.Collections;
    
    namespace server
    {
        class Program
        {
            public const int port = 50000;
    
            public static ArrayList clientList = new ArrayList();
            static void Main(string[] args)
            {
                new Program();
            }
    
            public Program()
            {
                TcpListener tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
                tcpListener.Start();
                while(true)
                {
                    Socket client = tcpListener.AcceptSocket();
                    IPEndPoint ip = (IPEndPoint) client.RemoteEndPoint;
                    Console.WriteLine("주소 {0}에서 접속", ip);
                    ClientListener clientThread = new ClientListener(client);
                    clientList.Add(clientThread);
                }
            }
        }
    
        class ClientListener
        {
            String id;
            Socket client;
            System.IO.StreamReader reader;
            System.IO.StreamWriter writer;
            public ClientListener(Socket client)
            {
                this.client = client;
                NetworkStream networkStream = new NetworkStream(client);
                this.reader = new System.IO.StreamReader(networkStream);
                this.writer = new System.IO.StreamWriter(networkStream);
                (new Thread(new ThreadStart(Run))).Start();
            }
            
            private void Run()
            {
                while(true)
                {
                    String line = "";
                    while(line.Equals(""))
                    {
                        line = reader.ReadLine();
                        if(line == null)
                        {
                            Program.clientList.Remove(this);
                            Console.WriteLine(this.id + "접속 종료");
                            return;
                        }
                    }
                    Console.WriteLine(client.RemoteEndPoint + "-send/" + line);
                    
                    String[] command = line.Split("/");
                    if(command[0].Equals("addMsg"))
                    {
                        foreach(object clientThread in Program.clientList)
                        {
                            ClientListener client = (ClientListener) clientThread;
                            Console.WriteLine(client.id);
                            if(!client.Equals(this))
                            {
                                NetworkStream networkStream = new NetworkStream(client.client);
                                System.IO.StreamWriter writer = new System.IO.StreamWriter(networkStream);
                                writer.WriteLine("addMsg/" + this.id + "/" + command[1]);
                                writer.Flush();
                            }
                        }
                    }
                    else if(command[0].Equals("id"))
                    {
                        this.id = command[1];
                    }
                }
            }
            public override bool Equals(Object obj)
            {
                //Check for null and compare run-time types.
                if ((obj == null) || ! this.GetType().Equals(obj.GetType())) 
                {
                    return false;
                }
                else { 
                    ClientListener other = (ClientListener) obj; 
                    return (this.id == other.id);
                }   
            }
            public override int GetHashCode() { return 0; } // 나중에 알아보기
        }
    }
    

     

    Client

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    
    namespace client
    {
        class Program
        {
            static void Main(string[] args)
            {
                TcpClient server;
                try
                {
                    server = new TcpClient("127.0.0.1", 50000);
                }
                catch (Exception)
                {
                    Console.WriteLine("서버와의 연결이 끊어졌습니다.");
                    return;
                }
    
                NetworkStream networkStream = server.GetStream();
                System.IO.StreamReader reader = new System.IO.StreamReader(networkStream);
                System.IO.StreamWriter writer = new System.IO.StreamWriter(networkStream);
    
                (new Thread(new ThreadStart(() =>
                {
                    while(true)
                    {
                        String line = "";
                        while(line.Equals(""))
                        {
                            line = reader.ReadLine();
                            if(line == null)
                            {
                                Console.WriteLine("서버와의 연결이 끊어졌습니다.");
                                return;
                            }
                        }
                        String[] command = line.Split("/");
                        if(command[0].Equals("addMsg"))
                        {
                            Console.WriteLine(command[1] + "/" + command[2]);
                        }
                    }
                }))).Start();
    
                String line = "";
                while(!line.Equals("quit"))
                {
                    line = Console.ReadLine();
                    writer.WriteLine(line);
                    writer.Flush();
                }
            }
        }
    }
    

    댓글