ソケットプログラミング入門


犯罪映画に秘密のレストランがあることを想像してみてください.
秘密のレストランには誰も入ることができず、位置も隠れています.顧客は顧客の代理人(アバンダ)を通じて秘密のレストランに入るしかない.秘密食堂の管理者は門番を教育して食堂の出入りを担当する.

レストランは代理人にレストランが用意した携帯電話を提供し、顧客と連絡を取る.お客様はドアマンに連絡して、レストランが提供した携帯電話の番号を調べて、代理人に連絡することができます.
上記の一連のプロセスはソケットプログラミングである.

それに比べて、携帯電話はコンセントで、取引先はクライアントで、代理は会話で、連絡(通話)はパケットの送受信で、レストランの管理人はサーバーで、ドアマンは受話器で、ドアマンの育成訓練はBindで、レストランの開放は受話器で、出入りを許可するのはAcceptです.
C#を使用して、これらのソケットプログラミングを下位レベルに実装します.
まず、レストランを実施するためにServer Coreプロジェクトを作成します.
コメントにはコードの説明が付いています.
    class Program
    {
        static void Main(string[] args)
        {
            //DNS(Domain Name System) 
            string host = Dns.GetHostName(); // DESKTOP-S7EG95G
            IPHostEntry ipHost = Dns.GetHostEntry(host); // System.Net.IPHostEntry
            IPAddress ipAddr = ipHost.AddressList[0];  // fe80::b599:93ca:869a:5736%18
            IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777); // 주소와 포트번호


            try // 에러가 날 위험이있다. 
            {
                // 문지기 == 문지기가 들고 있는 휴대폰(소켓)
                Socket listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                // 첫 번째 매개변수: IP 버전4 인지 버전6인지 
                // 그 다음 매개변수: TCP를 쓸건지 UDP를 쓸건지 

                // 문지기 교육 
                listenSocket.Bind(endPoint); // 식당주소와 비밀식당으로 가는 문을 문지기에게 교육 
                listenSocket.Listen(10); // 영업 개시 / 매개변수는 손님의 대기수

                while (true) // 식당(서버)은 계속 영업해야 하므로 무한루프 
                {
                    Console.WriteLine("Listening...");

                    // 손님 입장 허용 
                    Socket clientSocket = listenSocket.Accept(); // 반환값이 Socket임. 반환하는 Socket이 대리인에게 주는 핸드폰이다.

                    // 연락을 받는다. 
                    byte[] recvBuff = new byte[1024];
                    int recvBytesLength = clientSocket.Receive(recvBuff);
                    string recvData = Encoding.UTF8.GetString(recvBuff, 0, recvBytesLength); // 문자열을 받는다고 가정 
                    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());
            }

        }
次にDummyClientプロジェクトでお客様を実装します.
    class Program
    {
        static void Main(string[] args)
        {
            //DNS(Domain Name System) 
            string host = Dns.GetHostName(); // DESKTOP-S7EG95G
            IPHostEntry ipHost = Dns.GetHostEntry(host); // System.Net.IPHostEntry
            IPAddress ipAddr = ipHost.AddressList[0];  // fe80::b599:93ca:869a:5736%18
            IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777); // 주소와 포트번호

            try
            {
                //휴대폰 설정 == 소켓 생성
                Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                // 문지기한테 입장 문의 
                socket.Connect(endPoint); // Blocking 함수라 통신이 없으면 함수가 빠져나오지 못함. 
                Console.WriteLine($"Connected to {socket.RemoteEndPoint}");

                // 연락을 보낸다.
                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());
            }
           
ソリューションの[プロパティ]を変更してプロパティを変更し、DummyClientプロジェクトとServer Coreプロジェクトを同時に開始します.

Server Coreプロジェクトの出力ウィンドウ

DummyClientプロジェクトの出力ウィンドウ
次はRookissの回答が印象的でした
Q.
KakaoTalkのようなアプリケーションを利用して他の人とネットワークを利用して通信するのは、KakaoTalkアプリケーションでソケットプログラミングが使われているからでしょうか?すなわち,ネットワーク通信を介したプログラムはすべてソケットプログラミングを利用しているのだろうか.
A.
半分は正しい半分は違うネットワーク通信は基本的にアプリケーション内で自由に行うことができず,カーネル(オペレーティングシステム)に要求することによって間接的に行うしかないため,ソケットプログラミングはオペレーティングシステムに通信の受信と送信を要求する.したがって,ネットワーク通信を介したすべてのプログラムは「いつか」のソケットを利用している.
これは、アプリケーション開発者が直接ソケットプログラミングを行わなければならないという意味ではありません.特別な状況でなければ、この可能性はかえって低いです.
たとえば、NodeJSなどのWebフレームワークを使用すると、Lowbellレベルで一貫接続、パケット送信、接続解除などの操作を実行できます.
これは、関数を1つ呼び出すだけですべてのタスクを簡単に完了できるように非表示にするためです.これらの機能を組み合わせて作成したのは「フレームワーク」であり,Web通信は「Webフレームワーク」である.Webは、1回のリクエストのみを送信および/受信し、TCP通信切断とみなされることに注意してください.一方、オンラインゲームのように接続を維持し、データを交換し続ける必要がある場合は、ダイレクトソケットプログラミングを使用して、私たちのニーズを満たす必要があります.