VisualStudio/C#서버

[C#서버] 블로킹(Accept)와 논블로킹(AcceptAsync)

usingsystem 2022. 10. 27. 09:13
728x90

아래와 같이 Socket문법에서 Accept()는 블로킹 함수이다. 블로킹 함수란 무한정 대기한다는 뜻이다. 

무수한 유저를 받기위해서는 블로킹 함수를 채택하는 것 은 바람직 하지 않을 수 있다. 

결국 논블로킹 방법을 사용해야한다. 

 

동기방식인 블로킹 문법 Accept()

  Socket _listenSocket;
_listener.Accept()

비동기방식인 논블로킹 문법 AcceptAsync()

 internal 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);
        }

    }

Main

  static Listener _listener = new Listener();
        static void Main(string[] arg)
        {
            //DNS (Domain Name System) -> www.xxxxx.com
            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("Listen...");
            while (true)
            { ; }
        }
        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($"FromClient : {recvData}");
                //보낸다.
                byte[] sendBuff = Encoding.UTF8.GetBytes("Welcom");
                clientSocket.Send(sendBuff);

                //클라이언트 제거
                clientSocket.Shutdown(SocketShutdown.Both);//클라이언트에게 끊을 예정이란걸 알려줌
                clientSocket.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
728x90