📄 소켓 프로그래밍

지금까지 네트워크의 기본적인 이론을 다뤘다면, 이제부터 클라이언트와 서버 간 통신을 위한 프로그램을 작성해보도록 하겠습니다.

 

📑 Server

using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ServerCore
{
    class Program
    {
        private static void Main(string[] args)
        {
            //DNS 사용
            string host = Dns.GetHostName(); //현재 로컬의 호스트를 가져옴
            IPHostEntry ipHost = Dns.GetHostEntry(host);
            IPAddress ipAddress = ipHost.AddressList[0]; //배열로 들어있는 값 중에서 가장 첫번째 사용(임시)
            IPEndPoint endPoint = new IPEndPoint(ipAddress, 7777); //엔드포인트(ip주소와 포트번호)

            //리슨소켓 생성
            //TCP 통신을 사용 
            Socket listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                //리슨소켓 설정
                listenSocket.Bind(endPoint);

                //최대 대기수
                listenSocket.Listen(10);

                while (true)
                {
                    Console.WriteLine("Listening...");

                    //클라이언트와 연결
                    Socket clientSocket = listenSocket.Accept(); //다음 단계로 넘어갈 수 없으면 여기서 대기함 (블로킹)

                    //클라이언트로부터 수신
                    byte[] recieveBuffer = new byte[1024];
                    int recieveBytes = clientSocket.Receive(recieveBuffer); //recieveBuffer에 스트림을 넣고, 리턴값은 몇바이트를 받았는지 저장
                    string recieveData = Encoding.UTF8.GetString(recieveBuffer, 0, recieveBytes); //문자열로 획득
                    Console.WriteLine($"클라이언트로부터 받음: {recieveData}");

                    //클라이언트에게 송신
                    byte[] sendBuffer = Encoding.UTF8.GetBytes("Hello World From Server");
                    clientSocket.Send(sendBuffer);

                    //클라이언트 킥
                    clientSocket.Shutdown(SocketShutdown.Both); //미리 예고
                    clientSocket.Close(); //실질적으로 통신 해제
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

 

using System.Net;
using System.Net.Sockets;
using System.Text;
  • 소켓을 사용하기 위한 System.Net과, 스트림을 인코딩, 디코딩 할 System.Text를 추가합니다.

 

string host = Dns.GetHostName(); //현재 로컬의 호스트를 가져옴
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddress = ipHost.AddressList[0]; //배열로 들어있는 값 중에서 가장 첫번째 사용(임시)
IPEndPoint endPoint = new IPEndPoint(ipAddress, 7777); //엔드포인트(ip주소와 포트번호)
  • DNS를 사용하여 소켓통신을 구현합니다.
  • 테스트를 위해 자신의 호스트이름을 가져옵니다. 그 중 첫번째 IP주소를 획득한 후(임시) 지정한 포트(7777, 임시)로 엔드포인트를 생성합니다. 

 

Socket listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  • TCP 통신 프로토콜을 이용하는 소켓을 생성합니다.

 

//리슨소켓 설정
listenSocket.Bind(endPoint);

//최대 대기수
listenSocket.Listen(10);

생성한 소켓(리슨소켓)에 엔드포인트 정보를 넣어줍니다. (소켓 설정)

최대 대기수(backlog)는 10으로 지정하였습니다.(임시)

 

//클라이언트와 연결
Socket clientSocket = listenSocket.Accept(); //다음 단계로 넘어갈 수 없으면 여기서 대기함 (블로킹)
  • 클라이언트로부터 연결 요청이 들어오면 실행됩니다.
  • 연결 요청이 없는경우 이곳에서 대기합니다(블로킹)

 

//클라이언트로부터 수신
byte[] recieveBuffer = new byte[1024];
int recieveBytes = clientSocket.Receive(recieveBuffer); //recieveBuffer에 스트림을 넣고, 리턴값은 몇바이트를 받았는지 저장
string recieveData = Encoding.UTF8.GetString(recieveBuffer, 0, recieveBytes); //문자열로 획득
Console.WriteLine($"클라이언트로부터 받음: {recieveData}");
  • 리시브 버퍼를 만들어 클라이언트 소켓으로부터 온 정보를 담습니다.
  • 스트림을 String으로 변환하여 출력합니다.

 

//클라이언트에게 송신
byte[] sendBuffer = Encoding.UTF8.GetBytes("Hello World From Server");
clientSocket.Send(sendBuffer);
  • 클라이언트에게 송신합니다.

 

📑 Client

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace DummyClient
{
    class Program
    {
        static void Main(string[] args)
        {
            //DNS 사용
            string host = Dns.GetHostName(); //현재 로컬의 호스트를 가져옴
            IPHostEntry ipHost = Dns.GetHostEntry(host);
            IPAddress ipAddress = ipHost.AddressList[0];
            IPEndPoint endPoint = new IPEndPoint(ipAddress, 7777);

            //소켓 설정
            Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                //연결 시도
                socket.Connect(endPoint); //이곳에서 대기 (블로킹)

                //연결 된 경우 진행
                Console.WriteLine($"서버와 연결됨, {socket.RemoteEndPoint.ToString()}");

                //서버에게 송신
                byte[] sendBuffer = Encoding.UTF8.GetBytes("Hello World From Client");
                int sendBytes = socket.Send(sendBuffer);

                //서버로부터 수신
                byte[] recieveBuffer = new byte[1024];
                int recieveBytes = socket.Receive(recieveBuffer);
                string recieveData = Encoding.UTF8.GetString(recieveBuffer, 0, recieveBytes);
                Console.WriteLine($"서버로부터 수신: {recieveData}");

                //연결 해제
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

 

//연결 시도
socket.Connect(endPoint); //이곳에서 대기 (블로킹)
  • 동일한 방법으로 생성한 소켓(ip주소와 port가 동일)을 이용하여 연결을 시도합니다.
  • 연결할때까지 이곳에서 대기합니다(블로킹)

'server > socket server' 카테고리의 다른 글

[C# 서버] Async Session, Event  (0) 2023.02.06
[C# 서버] Async Listener  (0) 2023.01.17
[C# 서버] Thread Local Storage  (0) 2023.01.12
[C# 서버] ReaderWriterLock 구현  (0) 2023.01.11
[C# 서버] ReaderWriterLock  (0) 2023.01.10
bonnate