์ˆ˜์—…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace ServerCore
{
    class Listener
    {
        Socket _listenSocket;
        Action<Socket> _onAcceptHandler; // Accept ์™„๋ฃŒ ์‹œ ์‹คํ–‰ํ•  ํ•จ์ˆ˜

        public void Init(IPEndPoint endPoint, Action<Socket> onAcceptHandler)
        {
            // ๋ฌธ์ง€๊ธฐ ๊ต์œก
            _listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            _onAcceptHandler += onAcceptHandler;
            // ์˜์—… ์‹œ์ž‘
            // ์ตœ๋Œ€ ๋Œ€๊ธฐ์ˆ˜
            _listenSocket.Listen(10); // ์ตœ๋Œ€ ๋Œ€๊ธฐ ํ ํฌ๊ธฐ ์„ค์ •


            SocketAsyncEventArgs args = new SocketAsyncEventArgs();
            args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
            // ์ตœ์กฐ ํ•œ๋ฒˆ์€ ๋“ฑ๋ก์„ ํ•ด์ค˜์•ผํ•จ
            RegisterAccept(args);

        }
        void RegisterAccept(SocketAsyncEventArgs args)
        {
            args.AcceptSocket = null; // ์ด์ „ Accept ์†Œ์ผ“ ์ดˆ๊ธฐํ™”

            bool pending = _listenSocket.AcceptAsync(args); // ๋น„๋™๊ธฐ Accept ์‹คํ–‰ // ํŽœ๋”ฉ์„ ๋ฑ‰์–ด์คŒ
            if (pending == false) // ์ฆ‰์‹œ ์™„๋ฃŒ๋œ ๊ฒฝ์šฐ
                OnAcceptCompleted(null, args);
        }

        void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
        {
            if (args.SocketError == SocketError.Success)
            {
                // ์ฝœ๋ฐฑ ๋ฐฉ์‹์„ ์ด์šฉํ•ด์„œ ์ธ์ž๋กœ ๋ฐ›์•„์„œ ์™„๋ฃŒ๋˜๋ฉด ํ˜ธ์ถœ
                // ํด๋ผ์ด์–ธํŠธ Accept ์™„๋ฃŒ ํ›„ ์ฒ˜๋ฆฌ
                _onAcceptHandler.Invoke(args.AcceptSocket);
            }
            else
            {
                Console.WriteLine($"Accept Error: {args.SocketError}");
            }
            // ๋ชจ๋“  ์ผ์ด ๋๋‚จ ๋‹ค์Œ ํ„ด์„ ์œ„ํ•ด ์ค€๋น„ํ•ด๋‘ 
            RegisterAccept(args); // ๋‹ค์Œ Accept ์˜ˆ์•ฝ (๋‚š์‹œ์ค„ ๋‹ค์‹œ ๋˜์ง€๊ธฐ)
        }
        public Socket Accept()
        {
            return _listenSocket.Accept();// ๋น„๋™๊ธฐ ์˜๋ฏธ ์กฐ๊ธˆ ๋‚˜์ค‘์— ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋‹ค.
            // ์–ด๋–ค์‹์œผ๋กœ๋“  ์•Œ๋ ค์ค˜์•ผํ•จ
            // ๋น„๋™๊ธฐ๋Š” ๋งŽ์€ ์–ธ์–ด์—์„œ ์‚ฌ์šฉํ•จ
            // ์šฐ์„  ์•Œ์•„์•ผํ•  ๊ฒƒ์€ ์‹ค์ œ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ๋ถ€๋ถ„์ด ๋‘˜๋กœ ์ชผ๊ฐœ์ ธ์„œ ๋‘๋ฒˆ ๋งŒ๋“ค์–ด์•ผํ•จ

        }

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

namespace ServerCore
{
    class Program
    {

        static Listener _listener = new Listener();

        static void OnAcceptHandler(Socket clientSocket)
        {
            try
            {
                // 1๏ธ ํด๋ผ์ด์–ธํŠธ ๋ฐ์ดํ„ฐ ์ˆ˜์‹ 
                byte[] recvBuff = new byte[1024];
                int recvBytes = clientSocket.Receive(recvBuff);
                string recvData = Encoding.UTF8.GetString(recvBuff, 0, recvBytes);
                Console.WriteLine($"[From Client] {recvData}");

                // 2๏ธ ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต ์ „์†ก
                byte[] sendBuff = Encoding.UTF8.GetBytes("Welcome to MMORPG Server!");
                clientSocket.Send(sendBuff);

                // 3๏ธ ์†Œ์ผ“ ์ข…๋ฃŒ
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine($"[Error] {e}");
            }
        }
        // DNS (Domain Name System)
        // IP ์ฃผ์†Œ๋ฅผ ์ˆจ๊ฒจ์ฃผ๋Š” ๋„๋ฉ”์ธ ๋„ค์ž„์„ ์„ค์ •ํ•ด์คŒ
        static void Main(string[] args)
        {
            string host = Dns.GetHostName();
            IPHostEntry ipHost = Dns.GetHostEntry(host);
            IPAddress ipAddr = ipHost.AddressList[0];
            IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);

            // 2๏ธโƒฃ Listener ์ดˆ๊ธฐํ™” ๋ฐ Accept ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก
            _listener.Init(endPoint, OnAcceptHandler);
            Console.WriteLine("Server Listening...");

            while (true)
            {
                // ์„œ๋ฒ„๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š๋„๋ก ์œ ์ง€
            }



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

namespace DummyClient
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // DNS
            string host = Dns.GetHostName();
            IPHostEntry ipHost = Dns.GetHostEntry(host);
            IPAddress ipAddr = ipHost.AddressList[0];
            IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);

            while(true)
            {
                // ํœด๋Œ€ํฐ ์„ค์ •
                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 Server!");
                    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(100);
            }
            
            

        }
    }
}

โœ… ์ฃผ์ œ

  • ๋ณธ ๊ฐ•์˜๋Š” C# ๊ธฐ๋ฐ˜ TCP ๋„คํŠธ์›Œํฌ ์„œ๋ฒ„์—์„œ Listener ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ๋น„๋™๊ธฐ ์†Œ์ผ“ ์ˆ˜์‹  ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•œ๋‹ค.

  • ํŠนํžˆ SocketAsyncEventArgs์™€ AcceptAsync() ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•œ ๋น„๋™๊ธฐ Accept ์ฒ˜๋ฆฌ,
    Completed ์ด๋ฒคํŠธ, ์ฝœ๋ฐฑ ๊ตฌ์กฐ๋กœ ๋ถ„๋ฆฌ๋œ ์ˆ˜์‹  ์ฒ˜๋ฆฌ ๋ฐฉ์‹, ๋ฐ˜๋ณต ๋“ฑ๋ก ๊ธฐ๋ฐ˜์˜ ๋น„๋™๊ธฐ ๋ฃจํ”„ ๊ตฌ์กฐ์— ๋Œ€ํ•ด ์ฒ ์ €ํžˆ ๋ถ„์„ํ•œ๋‹ค.

  • Listener ํด๋ž˜์Šค์™€ ์‹ค์ œ ์„œ๋ฒ„ ์‹คํ–‰ ๊ตฌ์กฐ์ธ Program.cs ๊ฐ„์˜ ์—ฐ๊ฒฐ ๋ฐฉ์‹์„ ํ•™์Šตํ•œ๋‹ค.

  • Action<Socket> ํ˜•์‹์˜ ์ฝœ๋ฐฑ ๋“ฑ๋ก๊ณผ, ํด๋ผ์ด์–ธํŠธ ์ ‘์† ์‹œ ๋ฐ์ดํ„ฐ ์ˆ˜์‹ /์†ก์‹ /์ข…๋ฃŒ ํ๋ฆ„์„ ๊ตฌํ˜„ํ•˜๋Š” OnAcceptHandler(),
    DummyClient๋ฅผ ํ†ตํ•œ ๋ฐ˜๋ณต ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ๊นŒ์ง€ ๊ตฌ์„ฑํ•œ๋‹ค.

  • ์ด ํ๋ฆ„์„ ํ†ตํ•ด ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„ ๋น„๋™๊ธฐ ์†Œ์ผ“ ์ฒ˜๋ฆฌ์˜ ์™„์ „ํ•œ ์—ฐ๋™ ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•œ๋‹ค


๐Ÿ“š ๊ฐœ๋…

๐Ÿ”ธ Listener๋ž€?

  • Listener๋Š” ์„œ๋ฒ„ ์ธก์—์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ ์š”์ฒญ์„ ์ˆ˜์‹ (Accept)ํ•˜๊ธฐ ์œ„ํ•œ ๋ฌธ์ง€๊ธฐ ์—ญํ• ์˜ ์†Œ์ผ“์ด๋‹ค.
  • Listener ์†Œ์ผ“์€ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์ง€๋Š” ์•Š์œผ๋ฉฐ, ์˜ค๋กœ์ง€ ์—ฐ๊ฒฐ ์š”์ฒญ์„ ๋ฐ›๊ณ  ์ด๋ฅผ ์„ธ์…˜ ์ฒ˜๋ฆฌ ๋กœ์ง์— ๋„˜๊ธฐ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๐Ÿ”ธ ๋น„๋™๊ธฐ Accept ๋ฐฉ์‹์ด ํ•„์š”ํ•œ ์ด์œ 

  • ์ „ํ†ต์ ์ธ Accept() ํ•จ์ˆ˜๋Š” Blocking ํ•จ์ˆ˜๋กœ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ‘์†ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌดํ•œ ๋Œ€๊ธฐ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.
  • ์ˆ˜๋ฐฑ~์ˆ˜์ฒœ ๋ช…์˜ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋™์‹œ ์ ‘์†ํ•˜๋Š” ์‹ค์‹œ๊ฐ„ ์„œ๋ฒ„์—์„œ๋Š” ๋ธ”๋กœํ‚น ๊ตฌ์กฐ๋กœ๋Š” ์„œ๋ฒ„๊ฐ€ ์ •์ง€๋˜๊ธฐ ์‰ฝ๋‹ค.
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด AcceptAsync()์™€ SocketAsyncEventArgs๋ฅผ ํ™œ์šฉํ•œ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๋น„๋™๊ธฐ ์ˆ˜์‹  ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด ํ•„์ˆ˜์ ์ด๋‹ค.

๐Ÿ”ธ ์ฝœ๋ฐฑ ๋ฐฉ์‹์˜ ํ•„์š”์„ฑ

  • Listener๋Š” ๋‹จ์ˆœํžˆ ํด๋ผ์ด์–ธํŠธ ์ ‘์†์„ ์ˆ˜๋ฝ(Accept)๋งŒ ๋‹ด๋‹นํ•˜๋ฉฐ,
    ์—ฐ๊ฒฐ ์ดํ›„ ์–ด๋–ค ์ž‘์—…์„ ํ• ์ง€๋Š” ์™ธ๋ถ€์—์„œ ์ „๋‹ฌ๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜(Action<Socket>)๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ๋œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ์ฒ˜๋ฆฌ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•˜๋ฉด Listener๋Š” ๋”์šฑ ๋ฒ”์šฉ์ ์ด๊ณ  ์œ ์—ฐํ•˜๊ฒŒ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿ“˜ ์šฉ์–ด ์ •๋ฆฌ

์šฉ์–ด์„ค๋ช…
Listener ์†Œ์ผ“ํด๋ผ์ด์–ธํŠธ์˜ ์ ‘์† ์š”์ฒญ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„ ์ธก์— ์ƒ์‹œ ์—ด๋ ค ์žˆ๋Š” ์ˆ˜์‹  ์ „์šฉ ์†Œ์ผ“
Acceptํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๊ฒฐ์„ ์ˆ˜๋ฝํ•˜๊ณ  ์ƒˆ๋กœ์šด ํ†ต์‹ ์šฉ ์†Œ์ผ“์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ณผ์ •
AcceptAsync()Accept ์ž‘์—…์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, ๊ฒฐ๊ณผ๋Š” ์ด๋ฒคํŠธ๋กœ ํ†ต๋ณด๋ฐ›์Œ
SocketAsyncEventArgsAcceptAsync ๋“ฑ ๋น„๋™๊ธฐ ์†Œ์ผ“ ํ•จ์ˆ˜์˜ ์ƒํƒœ๋ฅผ ๋‹ด๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด
Completed ์ด๋ฒคํŠธAcceptAsync๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋“ฑ๋ก ์œ„์น˜
RegisterAccept()๋‹ค์Œ ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ์„ ์œ„ํ•œ AcceptAsync ๋“ฑ๋ก ํ•จ์ˆ˜
PendingAcceptAsync๊ฐ€ ์ฆ‰์‹œ ์™„๋ฃŒ๋˜์ง€ ์•Š๊ณ  ๋‚˜์ค‘์— ์™„๋ฃŒ๋  ์˜ˆ์ •์ด๋ผ๋Š” ์ƒํƒœ
Action<Socket>์†Œ์ผ“์„ ์ธ์ž๋กœ ๋ฐ›๋Š” ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ(์ฝœ๋ฐฑ ํ•จ์ˆ˜)
Invoke()๋“ฑ๋ก๋œ Action์„ ์‹คํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ
OnAcceptHandler()ํด๋ผ์ด์–ธํŠธ ์ ‘์† ์ดํ›„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ์ข…๋ฃŒ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์‹ค์ œ ํ•จ์ˆ˜
DummyClient์„œ๋ฒ„ ์ˆ˜์‹  ์ฒ˜๋ฆฌ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•œ ์ž๋™ ์ ‘์† ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋žจ

๐Ÿ’ป Listener ํด๋ž˜์Šค ์ฝ”๋“œ ๊ตฌ์กฐ

public 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);      // ๋ฌธ์ง€๊ธฐ ๊ต์œก
        _listenSocket.Listen(10);          // ์˜์—… ์‹œ์ž‘

        SocketAsyncEventArgs args = new SocketAsyncEventArgs();
        args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
        RegisterAccept(args);              // ์ตœ์ดˆ ๋‚š์‹œ์ค„ ๋˜์ง€๊ธฐ
    }

๐Ÿ” ์„ค๋ช…

  • Init() ํ•จ์ˆ˜๋Š” ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ ํ˜ธ์ถœ๋˜๋ฉฐ,
    ์†Œ์ผ“์„ ์ƒ์„ฑ โ†’ ๋ฐ”์ธ๋”ฉ โ†’ Listen(๋Œ€๊ธฐ์—ด ์„ค์ •) โ†’ ๋น„๋™๊ธฐ Accept ์ค€๋น„๊นŒ์ง€ ์ง„ํ–‰ํ•œ๋‹ค.
  • SocketAsyncEventArgs ๊ฐ์ฒด๋Š” Accept ์ž‘์—…์˜ ์ƒํƒœ ์ €์žฅ ๋ฐ ์™„๋ฃŒ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ์—ญํ• ์„ ํ•œ๋‹ค.
  • args.Completed += ... ๊ตฌ๋ฌธ์€ ๋น„๋™๊ธฐ Accept๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ˜ธ์ถœ๋  ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ณผ์ •์ด๋‹ค.

๐Ÿ’ป AcceptAsync ๋น„๋™๊ธฐ ๋“ฑ๋ก

    void RegisterAccept(SocketAsyncEventArgs args)
    {
        args.AcceptSocket = null; // ์ด์ „ ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์ œ๊ฑฐ

        bool pending = _listenSocket.AcceptAsync(args); // ๋น„๋™๊ธฐ ์ˆ˜์‹  ์š”์ฒญ

        if (pending == false)
        {
            // ๋ฐ”๋กœ ์™„๋ฃŒ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์ง์ ‘ ์ฝœ๋ฐฑ ํ˜ธ์ถœ
            OnAcceptCompleted(null, args);
        }
    }

๐Ÿ” ์„ค๋ช…

  • AcceptAsync()๋Š” ํ˜ธ์ถœ ์ฆ‰์‹œ true ๋˜๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • true: ์•„์ง ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—†๊ณ , ๋‚˜์ค‘์— Completed ์ด๋ฒคํŠธ๊ฐ€ ํ˜ธ์ถœ๋  ์˜ˆ์ •
    • false: ์ด๋ฏธ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ถ™์–ด ์žˆ์–ด ์ฆ‰์‹œ ์™„๋ฃŒ โ†’ ์ˆ˜๋™์œผ๋กœ OnAcceptCompleted() ํ˜ธ์ถœ ํ•„์š”
  • args.AcceptSocket = null์€ ์ด์ „ Accept ์ž‘์—…์˜ ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์ •๋ณด๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ํ•„์ˆ˜ ์ฒ˜๋ฆฌ์ด๋‹ค.
    • ์ œ๊ฑฐํ•˜์ง€ ์•Š์œผ๋ฉด "SocketAsyncEventArgs ์ด๋ฏธ ์†Œ์ผ“์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค" ์˜ค๋ฅ˜ ๋ฐœ์ƒ

๐Ÿ’ป Accept ์™„๋ฃŒ ์ฝœ๋ฐฑ ์ฒ˜๋ฆฌ

    void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
    {
        if (args.SocketError == SocketError.Success)
        {
            // ์™ธ๋ถ€์—์„œ ์ „๋‹ฌ๋ฐ›์€ ํด๋ผ์ด์–ธํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ์‹คํ–‰
            _onAcceptHandler.Invoke(args.AcceptSocket);
        }
        else
        {
            Console.WriteLine($"Accept Error: {args.SocketError}");
        }

        // ๋‹ค์Œ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•ด ๋‹ค์‹œ ๋‚š์‹œ์ค„ ๋“ฑ๋ก
        RegisterAccept(args);
    }
}

๐Ÿ” ์„ค๋ช…

  • OnAcceptCompleted()๋Š” AcceptAsync๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์ž๋™ ํ˜ธ์ถœ๋˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋‹ค.
  • args.SocketError๊ฐ€ ์„ฑ๊ณต์ผ ๊ฒฝ์šฐ, args.AcceptSocket์— ํด๋ผ์ด์–ธํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์„ธ์…˜ ์†Œ์ผ“์ด ๋‹ด๊ฒจ ์žˆ๋‹ค.
  • ์ด ์†Œ์ผ“์€ _onAcceptHandler.Invoke()๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€ ์ฒ˜๋ฆฌ ๋กœ์ง(์˜ˆ: ๋ฐ์ดํ„ฐ ์ˆ˜์‹ )์œผ๋กœ ์ „๋‹ฌ๋œ๋‹ค.
  • ๋งˆ์ง€๋ง‰์—๋Š” ๋ฐ˜๋“œ์‹œ ๋‹ค์‹œ RegisterAccept()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋‹ค์Œ ํด๋ผ์ด์–ธํŠธ ์ ‘์† ๋Œ€๊ธฐ๋ฅผ ์ด์–ด๊ฐ„๋‹ค.

๐Ÿ” ์ „์ฒด ํ๋ฆ„ ์š”์•ฝ (๋น„์œ : ๋‚š์‹œ ๊ตฌ์กฐ)

[Init()]
   โ†“
RegisterAccept(args)   โ† ๋‚š์‹œ๋Œ€๋ฅผ ๋˜์ง„๋‹ค
   โ†“
ํด๋ผ์ด์–ธํŠธ ์ ‘์†
   โ†“
AcceptAsync ์™„๋ฃŒ
   โ†“
OnAcceptCompleted()    โ† ๋ฌผ๊ณ ๊ธฐ ์žก์•˜๋‹ค
   โ†“
_onAcceptHandler()     โ† ์†๋‹˜ ์‘๋Œ€
   โ†“
RegisterAccept(args)   โ† ๋‹ค์Œ ์†๋‹˜ ๊ธฐ๋‹ค๋ฆผ

๐Ÿ’ป ์ฝ”๋“œ ๋ถ„์„ โ€” Program.cs ๊ตฌ์กฐ

โœ… Main ํ•จ์ˆ˜

static void Main(string[] args)
{
    string host = Dns.GetHostName();
    IPHostEntry ipHost = Dns.GetHostEntry(host);
    IPAddress ipAddr = ipHost.AddressList[0];
    IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);

    _listener.Init(endPoint, OnAcceptHandler);  // Listener ์ดˆ๊ธฐํ™” ๋ฐ ์ฝœ๋ฐฑ ๋“ฑ๋ก

    Console.WriteLine("Server Listening...");

    while (true)
    {
        ; // ์„œ๋ฒ„๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š๋„๋ก ์œ ์ง€
    }
}

๐Ÿ” ์„ค๋ช…

  • ์„œ๋ฒ„ ์‹คํ–‰ ์‹œ Init() ํ˜ธ์ถœ์„ ํ†ตํ•ด Listener๊ฐ€ ์†Œ์ผ“ ์ƒ์„ฑ, ๋ฐ”์ธ๋”ฉ, Listen, AcceptAsync ๋“ฑ๋ก์„ ์ˆ˜ํ–‰
  • ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ OnAcceptHandler๋ฅผ ์ „๋‹ฌ โ†’ Accept๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์‹คํ–‰๋  ํด๋ผ์ด์–ธํŠธ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ๋„˜๊ธด ๊ฒƒ
  • ์„œ๋ฒ„๋Š” ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ํ†ตํ•ด ์ข…๋ฃŒ๋˜์ง€ ์•Š๊ณ  ์‹คํ–‰ ์ƒํƒœ ์œ ์ง€

โœ… OnAcceptHandler ํ•จ์ˆ˜

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($"[Error] {e}");
    }
}

๐Ÿ” ์„ค๋ช…

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ‘์†ํ•˜๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๋ฉด Receive()๋กœ ์ˆ˜์‹  ์ฒ˜๋ฆฌ
  • ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ถœ๋ ฅ ํ›„, ์„œ๋ฒ„์—์„œ ํ™˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ  ์†Œ์ผ“์„ ์ข…๋ฃŒ
  • ์ด ๊ตฌ์กฐ๋Š” ํ–ฅํ›„ Session ํด๋ž˜์Šค๋กœ ๋Œ€์ฒด๋˜์–ด ํด๋ผ์ด์–ธํŠธ์™€์˜ ์ง€์† ํ†ต์‹  ๊ตฌ์กฐ๋กœ ๋ฐœ์ „ํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿ’ป ์ฝ”๋“œ ๋ถ„์„ โ€” DummyClient ๊ตฌ์กฐ

โœ… ๋ฐ˜๋ณต ์ ‘์† ํ…Œ์ŠคํŠธ์šฉ ํด๋ผ์ด์–ธํŠธ

while (true)
{
    Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

    try
    {
        socket.Connect(endPoint);
        Console.WriteLine($"Connected to {socket.RemoteEndPoint}");

        byte[] sendBuff = Encoding.UTF8.GetBytes("Hello Server!");
        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(100);  // 0.1์ดˆ๋งˆ๋‹ค ๋ฐ˜๋ณต ์ ‘์†
}

๐Ÿ” ์„ค๋ช…

  • 0.1์ดˆ๋งˆ๋‹ค ์„œ๋ฒ„์— ์ƒˆ๋กœ ์ ‘์†ํ•˜์—ฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ์ˆ˜์‹ ํ•œ ํ›„ ์ข…๋ฃŒ
  • ์„œ๋ฒ„์˜ AcceptAsync()๊ฐ€ ๋น„๋™๊ธฐ๋กœ ์ž˜ ๋“ฑ๋ก๋˜์–ด ์žˆ๋‹ค๋ฉด ๋Š๊น€ ์—†์ด ๋ชจ๋“  ์š”์ฒญ์„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • ์‹ค์ „ ์„œ๋ฒ„์—์„œ๋Š” ์ˆ˜๋ฐฑ ๋ช…์˜ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋™์‹œ์— ์—ฐ๊ฒฐ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ํ™˜๊ฒฝ์„ ์ด ๊ตฌ์กฐ๋กœ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ

๐Ÿ” Listener์™€ Program ์ „์ฒด ํ๋ฆ„ ์š”์•ฝ

[Main()]
  โ†“
_listener.Init(endpoint, OnAcceptHandler)   โ† ์ฝœ๋ฐฑ ๋“ฑ๋ก
  โ†“
RegisterAccept(args)                        โ† ๋‚š์‹œ๋Œ€ ๋˜์ง
  โ†“
ํด๋ผ์ด์–ธํŠธ ์ ‘์† (DummyClient)
  โ†“
AcceptAsync ์™„๋ฃŒ
  โ†“
OnAcceptCompleted()
  โ†“
_onAcceptHandler.Invoke(socket)
     โ†“
    Receive, Send, Close
  โ†“
๋‹ค์‹œ RegisterAccept(args)

โœ… ํ•ต์‹ฌ ์š”์•ฝ

ํ•ญ๋ชฉ๋‚ด์šฉ
Listener ํด๋ž˜์Šคํด๋ผ์ด์–ธํŠธ ์ ‘์†์„ ์ˆ˜์‹ ํ•˜๊ณ , ์™ธ๋ถ€ ์ฝœ๋ฐฑ์œผ๋กœ ์—ฐ๊ฒฐ ์ฒ˜๋ฆฌ ์œ„์ž„
AcceptAsync๋น„๋™๊ธฐ Accept ์š”์ฒญ ํ•จ์ˆ˜๋กœ, ์ž‘์—… ์™„๋ฃŒ ์‹œ ์ด๋ฒคํŠธ ๋ฐœ์ƒ
SocketAsyncEventArgsAcceptAsync์˜ ์ƒํƒœ ๋ณด๊ด€ + ์ด๋ฒคํŠธ ์ „๋‹ฌ ๊ฐ์ฒด
RegisterAcceptํด๋ผ์ด์–ธํŠธ ์ˆ˜์‹  ๋Œ€๊ธฐ ๋“ฑ๋ก (๋‚š์‹œ์ค„ ๋˜์ง€๊ธฐ)
OnAcceptCompletedAccept ์™„๋ฃŒ ์‹œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์ฒ˜๋ฆฌ
๋ฐ˜๋ณต ํ๋ฆ„RegisterAccept โ†’ AcceptAsync โ†’ OnAcceptCompleted โ†’ ๋‹ค์‹œ RegisterAccept
์ฝœ๋ฐฑ ๋“ฑ๋ก ๊ตฌ์กฐListener๋Š” ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์ดํ›„์˜ ๋กœ์ง์„ ์™ธ๋ถ€์— ์œ„์ž„ํ•จ
OnAcceptHandler์‹ค์ œ ๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹  ๋ฐ ์—ฐ๊ฒฐ ์ข…๋ฃŒ ์ฒ˜๋ฆฌ ๋‹ด๋‹น
DummyClient๋ฐ˜๋ณต ์ ‘์† ํ…Œ์ŠคํŠธ๋กœ Listener ๊ตฌ์กฐ์˜ ์•ˆ์ •์„ฑ ๊ฒ€์ฆ
ํ๋ฆ„ ๋ฐ˜๋ณตAcceptAsync โ†’ ์™„๋ฃŒ โ†’ _onAcceptHandler ์‹คํ–‰ โ†’ RegisterAccept ์žฌ๋“ฑ๋ก

profile
๏งกๅฎถ๋„ค_๊ณต๋ถ€๋ฐฉ

0๊ฐœ์˜ ๋Œ“๊ธ€