๐Ÿ™‡โ€โ™€๏ธListener

๋ฌธ์ง€๊ธฐ๋ฅผ ๋”ฐ๋กœ ๋นผ์ž!

  • Accept, Receive, Send ๋“ฑ ๋ชจ๋“  ์ž…์ถœ๋ ฅ ํ•จ์ˆ˜๋“ค์€ ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ํ•ด์•ผ ๋จ
  • ์ผ๋‹จ ์˜ˆ์•ฝ์„ ํ•ด๋†“๊ณ  ์†๋‹˜์ด ๋“ค์–ด์˜ค๋ฉด ์ž‘๋™ํ•˜๊ฒŒ ๋” ๋งŒ๋“ค๊ธฐ (์ด๋ฒคํŠธ ๋ฐฉ์‹)

  • ๋‚š์‹œ ์˜ˆ์‹œ
    • ์ฒ˜์Œ์—๋Š” ๋‚š์‹œ๋Œ€๋ฅผ ์ง์ ‘ ๋˜์ง€๊ธฐ
    • ์ž…์งˆ์ด ๋ฐ”๋กœ ์˜ค๋ฉด ๋ฐ”๋กœ ํ• ์ผํ•˜๊ธฐ
    • ์ž…์งˆ์ด ์•ˆ์˜ค๋ฉด ์˜ฌ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋‹ค๊ฐ€ ์˜ค๋ฉด ํ• ์ผํ•˜๊ธฐ
    • ํ• ์ผ์ด ๋๋‚ฌ์œผ๋ฉด ๋‹ค์‹œ ๋‚š์‹œ๋Œ€ ๋˜์ง€๊ธฐ

ServerCore๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ฐ”๋€œ

args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAccepteCompleted); ์ž˜ ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„ => ๊ทธ๋ƒฅ ์ด๋ ‡๊ฒŒ ์“ฐ๋Š”๊ฑด๊ฐ‘๋‹ค ํ•ด์•ผ๋จ

๊ฒŒ์ž„์—๋Š” ๋น„๋™๊ธฐํ•จ์ˆ˜๋ฅผ ์จ์•ผํ•œ๋‹ค - Accept => AcceptAsync

Async๊ณ„์—ด์˜ ํ•จ์ˆ˜๋“ค์€ ๊ทธ ํ–‰๋™์„ ํ–ˆ๋“  ์•ˆํ–ˆ๋“  ์ผ๋‹จ ๋ฆฌํ„ด์„ ํ•จ -> ์ผ์„ ์•ˆํ–ˆ์„ ๋• ์ผ๋‹จ ๋น ์ ธ๋‚˜๊ฐ”์œผ๋‹ˆ๊นŒ ๋‹ค์‹œ ์•Œ๋ ค์ค˜์•ผํ•จ ( ์ด๋ฒคํŠธ ๋ฐฉ์‹) ์ผ์„ ์š”์ฒญํ•˜๋Š” ๋ถ€๋ถ„๊ณผ ์‹ค์ œ ์ผ์„ ํ•˜๋Š” ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋‰œ๋‹ค - RegisterAccept, OnAcceptCompleted

pending = ๋ฏธ๊ฒฐ์ •์˜ pending == false ์‹คํ–‰๊ณผ ๊ฑฐ์˜ ๋™์‹œ์— ํด๋ผ์—์„œ ์ ‘์†์ด ์˜จ ๊ฒฝ์šฐ

args.Completed ๋Š” EventHandler๋ฐฉ์‹์œผ๋กœ ์ด๋ฒคํŠธ ๋ฐฉ์‹์œผ๋กœ ์ฝœ๋ฒก์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹

Action _onAcceptHandler๋ฅผ ๋งŒ๋“  ์ด์œ  - Accept๋ฅผ ํ•œ ์ด์œ ์˜ ํ–‰๋™๋“ค์„ ์ด๋ฒคํŠธ ํ˜•์‹์œผ๋กœ ๋ฐ›์•„์„œ ์†Œ์ผ“์ด ๊ทธ ์ผ์„ ํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•˜์—ฌ, _onAcceptHandler.Invoke(args.AcceptSocket);์ด ๋˜๋Š” ๊ฒƒ!, args.AcceptSocket์€ args๊ฐ€ AcceptAsync๋ฅผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์ง„ Socket์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ ๋“ฏ

Async๊ณ„์—ด์˜ ํ•จ์ˆ˜๋“ค์€ ๋‹น์žฅ์€ ๊ฐ’์„ ๋ฝ‘์•„์˜ฌ ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— SocketAsyncEventArgs๊ฐ€ ์ด๋Ÿฐ์ €๋Ÿฐ ์ •๋ณด๋“ค์„ ๊ฐ€์ ธ์™€์„œ ์ „๋‹ฌํ•ด์ฃผ๋Š” ๋Š๋‚Œ

ํ”„๋กœ๊ทธ๋žจ์—์„œ Socket์„ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ Init(IPEndPoint, Action)์— ๋งž์ถฐ์ค€๋‹ค

๐ŸชListener๋ถ„์„

class Listener
{
    Socket _listenSocket; // ๋ฆฌ์Šค๋„ˆ ์†Œ์ผ“ ์ƒ์„ฑ
    Action<Socket> _onAcceptHandler; // ์ด๋ฒคํŠธ ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ

    public void Init(IPEndPoint endPoint, Action<Socket> onAcceptHandler) // ์ด๋‹›ํ• ๋•Œ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ๊นŒ์ง€ ํ•ด์คŒ
    {
        // ๋ฌธ์ง€๊ธฐ
        _listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // ๋ฆฌ์Šค๋„ˆ ์†Œ์ผ“ ์—ฐ๊ฒฐ
        _onAcceptHandler += onAcceptHandler; // ์ด๋ฒคํŠธ ๊ตฌ๋… ์‹ ์ฒญ

        // ๋ฌธ์ง€๊ธฐ ๊ต์œก
        _listenSocket.Bind(endPoint); // ๋ฐ”์ธ๋“œ ๊ฒฐํ•ฉ

        // ์˜์—… ์‹œ์ž‘
        // BackLog : ์ตœ๋Œ€ ๋Œ€๊ธฐ์ˆ˜
        _listenSocket.Listen(10); // ์ผ๊พผ ์ˆ˜ ์„ค์ •

        SocketAsyncEventArgs args = new SocketAsyncEventArgs(); // ์ด๋ฒคํŠธ ํ˜•์‹ ์š”์ • ์ƒ์„ฑ
        args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted); // ์ปดํ”Œ๋ฆฟ ๊ตฌ๋… ์‹ ์ฒญ
        RegisterAccept(args); // ์ฒซ ๋‚š์‹œ๋Œ€ ๋˜์ง€๊ธฐ
    }

    void RegisterAccept(SocketAsyncEventArgs args) // ์–ด์…‰ ๋“ฑ๋กํ•˜๊ธฐ ํ•จ์ˆ˜, ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ ๋•Œ๋งค SocketAsyncEventArgs args ์ธ์ž๊ฐ€ ํ•„์š”
    {
        args.AcceptSocket = null; // ๋‘๋ฒˆ์งธ ํ„ด๋ถ€ํ„ฐ ๋‚จ์•„์žˆ๋Š” ๊ฐ’์œผ๋กœ ์—๋Ÿฌ๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐํ™” ์‹œ์ผœ์ฃผ๊ธฐ

        bool pending = _listenSocket.AcceptAsync(args); // ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ ํŒฌ๋”ฉ ์œ ๋ฌดํ™•์ธ
        if (pending == false) // ํŒฌ๋”ฉ์ด ์—†๋‹ค๋Š” ๊ฑด ๋‚š์‹œ๋Œ€๋ฅผ ๋„ฃ์ž๋งˆ์ž ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ๋‚š์ด๋Š” ๊ฒƒ
            OnAcceptCompleted(null, args);
    }

    void OnAcceptCompleted(object sender, SocketAsyncEventArgs args) // ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ ๋•Œ๋งค object sender, SocketAsyncEventArgs args ์ธ์ž๊ฐ€ ํ•„์š”
    {
        if (args.SocketError == SocketError.Success) // ์—๋Ÿฌ๊ฐ€ ์—†์ด ์ž˜ ์„ฑ๊ณตํ–ˆ์„ ๋•Œ
        {
            _onAcceptHandler.Invoke(args.AcceptSocket); // ์„œ๋ฒ„์ฝ”์–ด์— ์žˆ๋Š” ์ผ ์‹œํ‚ค๊ธฐ (์ด๋ฒคํŠธ ๋ฐœ์†ก)
        }
        else
            Console.WriteLine(args.SocketError.ToString()); // ๋ฌด์Šจ ์—๋Ÿฌ์ธ์ง€ ํ™•์ธํ•˜๊ธฐ

        RegisterAccept(args); // ๋‹ค๋๋‚ฌ์œผ๋ฉด ๋‹ค์‹œ ๋‚š์‹œ๋Œ€ ๋˜์ง€๊ธฐ
    }
}

args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted); // ์–ด์‹ฑํฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์–ด์‹ฑํฌ์•„๊ทœ๋จผ์ธ ๋ฅผ ๋„ฃ์–ด์ค€๊ฒฝ์šฐ ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š” ๋ณ„๋„์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ

void OnAcceptCompleted(object sender, SocketAsyncEventArgs args) // ๋ ˆ๋“œ์กด, ์“ฐ๋ ˆ๋“œ๋‚˜ ํ…Œ์Šคํฌ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•˜์ง€๋งŒ ์ž๋™์ ์œผ๋กœ ํ’€์—์„œ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•จ

๐ŸชListner, DummyClient, ServerCore ์ „์ฒด ์ฝ”๋“œ

  • Listner
    namespace ServerCore
    {
      class Listener
      {
          Socket _listenSocket;
          Action<Socket> _onAcceptHandler;
    
          public void Init(IPEndPoint endPoint, Action<Socket> onAcceptHandler)
          {
              // ๋ฌธ์ง€๊ธฐ
              _listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
              _onAcceptHandler += onAcceptHandler;
    
              // ๋ฌธ์ง€๊ธฐ ๊ต์œก
              _listenSocket.Bind(endPoint);
    
              // ์˜์—… ์‹œ์ž‘
              // BackLog : ์ตœ๋Œ€ ๋Œ€๊ธฐ์ˆ˜
              _listenSocket.Listen(10);
    
              SocketAsyncEventArgs args = new SocketAsyncEventArgs();
              args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
              RegisterAccept(args);
          }
    
          void RegisterAccept(SocketAsyncEventArgs args)
          {
              args.AcceptSocket = null;
    
              bool pending = _listenSocket.AcceptAsync(args);
              if (pending == false)
                  OnAcceptCompleted(null, args);
          }
    
          void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
          {
              if (args.SocketError == SocketError.Success)
              {
                  _onAcceptHandler.Invoke(args.AcceptSocket);
              }
              else
                  Console.WriteLine(args.SocketError.ToString());
    
              RegisterAccept(args);
          }
    
          public Socket Accept()
          {
                
              return _listenSocket.Accept();
          }
      }
    }
    
  • DummyClient
    namespace DummyClient
    {
      class Program
      {
          static void Main(string[] args)
          {
              while (true)
              {
                  // DNS (Domain Name System)
                  string host = Dns.GetHostName();
                  IPHostEntry ipHost = Dns.GetHostEntry(host);
                  IPAddress ipAddr = ipHost.AddressList[0];
                  IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
    
                  // ํœด๋Œ€ํฐ ์„ค์ •
                  Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    
                  try
                  {
                      // ๋ฌธ์ง€๊ธฐํ•œํ…Œ ์ž…์žฅ ๋ฌธ์˜
                      socket.Connect(endPoint);
                      Console.WriteLine($"Connected to {socket.RemoteEndPoint.ToString()}");
    
                      // ๋ณด๋‚ธ๋‹ค
                      byte[] sendBuff = Encoding.UTF8.GetBytes("Hello World!");
                      int sendBytes = socket.Send(sendBuff);
    
                      // ๋ฐ›๋Š”๋‹ค
                      byte[] recvBuff = new byte[1024];
                      int recvBytes = socket.Receive(recvBuff);
                      string recvData = Encoding.UTF8.GetString(recvBuff, 0, recvBytes);
                      Console.WriteLine($"[From Server] {recvData}");
    
                      // ๋‚˜๊ฐ„๋‹ค
                      socket.Shutdown(SocketShutdown.Both);
                      socket.Close();
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine(e.ToString());
                  }
    
                  Thread.Sleep(500);
              }
          }
      }
    }
    
  • ServerCore
    namespace ServerCore
    {
      class Program
      {
          static Listener _listener = new Listener();
    
          static void OnAcceptHandler(Socket clientSocket)
          {
              try
              {
                  // ๋ฐ›๋Š”๋‹ค
                  byte[] recvBuff = new byte[1024];
                  int recvBytes = clientSocket.Receive(recvBuff);
                  string recvData = Encoding.UTF8.GetString(recvBuff, 0, recvBytes);
                  Console.WriteLine($"[From Client] {recvData}");
    
                  // ๋ณด๋‚ธ๋‹ค
                  byte[] sendBuff = Encoding.UTF8.GetBytes("Welcome to MMORPG Server!");
                  clientSocket.Send(sendBuff);
    
                  // ์ซ“์•„๋‚ธ๋‹ค
                  clientSocket.Shutdown(SocketShutdown.Both);
                  clientSocket.Close();
              }
              catch (Exception e)
              {
                  Console.WriteLine(e.ToString());
              }
          }
    
          static void Main(string[] args)
          {
              // DNS (Domain Name System)
              string host = Dns.GetHostName();
              IPHostEntry ipHost = Dns.GetHostEntry(host);
              IPAddress ipAddr = ipHost.AddressList[0];
              IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
    
              _listener.Init(endPoint, OnAcceptHandler);
    
              Console.WriteLine("Listening...");
              while (true)
              {
                  ;
              }
    
          }
      }
    }
    

ํƒœ๊ทธ:

์นดํ…Œ๊ณ ๋ฆฌ:

์—…๋ฐ์ดํŠธ: