본문 바로가기
프로그래밍 언어/C#

[C#] TCP/IP 소켓 통신 (Server/Client)

by mssil-7 2024. 7. 15.

TCP/IP 통신을 하기 위해 소켓(Socket)을 이용합니다. 소켓은 각 포트를 사용하여 통신을 수행하는 도구로 각 프로그램에 포트를 세팅하고 소켓으로 데이터를 주고 받습니다. 즉, 포트는 출입구라하면 소켓은 데이터를 직접 송수신하는 매체가 됩니다. 

 

using System.Net.Sockets;

 

1. Server Socket

 

servet socket의 역할은 client socket의 연결 요청을 대기하고, 연결 요청이 오면 클라이언트 소켓을 생성하여 통신을 가능하게 합니다.

 

 class Server
    {
        public delegate void ServerConnectCallback(bool bStatus);
        public delegate void ServerCallback(string msg);

        TcpListener server;
        TcpClient client;

        NetworkStream stream;
        ServerConnectCallback callConnectback;
        ServerCallback callback;

        public Server(ServerConnectCallback callbackDelegate)
        {
            callConnectback = callbackDelegate;
        }

        public Server(ServerCallback callbackDelegate)
        {
            callback = callbackDelegate;
        }


        public bool Connect(string ip, string port)
        {
            try
            {
                IPAddress localAddr = IPAddress.Parse(ip);
                server = new TcpListener(localAddr, Convert.ToInt32(port));

                server.Start();
                return true;
            }
            catch
            {
                return false;
            }
        }
            

        public void ConnectThread()
        {
            while (true)
            {
                client = server.AcceptTcpClient();
                stream = client.GetStream();

                callConnectback(true);
            }
        }


        public void RecvThread()
        {
            while (true)
            {
                client = server.AcceptTcpClient();
                stream = client.GetStream();

                Thread serverRecvThread = new Thread(new ThreadStart(Recv));
                serverRecvThread.Start();
            }
        }


        public void Send(string data)
        {
            byte[] responseBuffer = Encoding.UTF8.GetBytes(data);
            stream.Write(responseBuffer, 0, responseBuffer.Length);
        }

        public void Recv()
        {
            byte[] buffer = new byte[1024];
            

            while (true)
            {
                if (stream != null)
                {
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
                    string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    if (data != "")
                    {
                        callback(data);
                    }

                }
                
            }
        }

        public void Disconnect()
        {
            stream.Close();
            client.Close();

        }

    }

 

    public void ServerConnect()
    {
        Server server= new Server(new Server.ServerCallback(ServerResultCallback));
        bool status = server.Connect(IP, Port);

        if (status)
        {
            Thread serverSendThread = new Thread(new ThreadStart(server.RecvThread));
            serverSendThread.IsBackground = true;
            serverSendThread.Start();
        }
    }

    public void ServerResultCallback(string recv)
    {
        Console.WriteLine("Server Recv : " + recv);
    }

 

2. Client Socket

 

client socket은 대기 없이 바로 사용 가능하며, 실제로 데이터 송수신이 일어나는 곳입니다. 

 

    class Client
    {
        public delegate void ClientCallback(string msg);
        
        TcpClient client;
        NetworkStream stream;
        ClientCallback callback;

        public Client(ClientCallback callbackDelegate)
        {
            callback = callbackDelegate;
        }

        public bool Connect(string ip, string port)
        {
            try
            {
                client = new TcpClient(ip, Convert.ToInt32(port));
                stream = client.GetStream();
                return true;
            }
            catch
            {
                return false;
            }
        }


        public void Send(string msg)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(msg);

            stream.Write(buffer, 0, buffer.Length);
        }

        
        public void Recv()
        {
            byte[] buffer = new byte[1024];

            while (true)
            {
                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                callback(response);
            }

        }


        public void Disconnect()
        {
            stream.Close();
            client.Close();
        }

 

    public void ClientConnect()
    {
        Client client = new Client(new Client.ClientCallback(ClientResultCallback));
        bool status = client.Connect(IP, Port);

        if (status)
        {
            Thread clientThread = new Thread(new ThreadStart(client.Recv));
            clientThread.IsBackground = true;
            clientThread.Start();
        }
    }

    public void ClientResultCallback(string recv)
    {
        Console.WriteLine("Client Recv : " + recv);
    }