0

以下に示すように、クライアント/サーバー アプリケーションの一連の要件があります。

1) プログラムは、事前定義された UDP ポートでリッスンしているホストにstatuscheckメッセージを送信します。このメッセージは、OS によって指定された送信元ポート番号で送信されます。

2) プログラムは、リモート ホストからの応答を受信するために、手順 1 で開始されたソース ポート番号をリッスンする必要があります。したがって、プログラムは同時に何千ものポートをリッスンする必要があります。

3) このプロセスは、毎分数千のホストに対して実行する必要があります

以下に、この動作を模倣するために多数のリクエストを Echo Server に送信するサンプル例を作成しました。私が直面している問題は、リモート ホストからデータを受信した後に各ソケットを閉じても、約 16,000 のリクエストの後に、システムに十分なバッファー スペースがないか、キューがいっぱいであるという例外がスローされることです。

そのような要件を達成する方法は何でしょうか?

public void SendChecks()
        {
            IPEndPoint ip = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 7);
            for (int i = 0; i < 200000; i++)
            {

                Socket _UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                stateobject so = new stateobject(_UdpSocket);

                IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
                EndPoint tempRemoteEP = (EndPoint)sender;

                _UdpSocket.Bind(tempRemoteEP);

                string welcome = "Hello";
                byte[] data = new byte[5];
                data = Encoding.ASCII.GetBytes(welcome);

                _UdpSocket.BeginSendTo(data, 0, data.Length, SocketFlags.None, ip, new AsyncCallback(OnSend), _UdpSocket);

                //Start listening to the message send by the user
                EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);

                _UdpSocket.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None, ref newClientEP, new AsyncCallback(DoReceiveFrom), so);

            }
        }

        private void DoReceiveFrom(IAsyncResult ar)
        {
            try
            {
                stateobject so = (stateobject)ar.AsyncState;

                Socket s = so.sock;

                // Creates a temporary EndPoint to pass to EndReceiveFrom.
                IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
                EndPoint tempRemoteEP = (EndPoint)sender;

                int read = s.EndReceiveFrom(ar, ref tempRemoteEP);

                so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read))
                //All the data has been read, so displays it to the console. 
                string strContent;
                strContent = so.sb.ToString();
                Console.WriteLine(String.Format("Read {0} byte from socket" +"data = {1} ", strContent.Length, strContent));

                s.Close();
                s.Dispose();                    
            }

            catch (Exception ex)
            {                
               Console.WriteLine(ex);  
            }
        }

        private void OnSend(IAsyncResult ira)
        {
            Socket s = (Socket)ira.AsyncState;
            Console.WriteLine("Sent Data To Sever on port {0}",((IPEndPoint)s.LocalEndPoint).Port);

            s.EndSend(ira);
        }
    }
4

1 に答える 1

1

パフォーマンスとシンプルさの点で最善の方法は、次のいずれかの場所で単一のポート番号を使用することだと思います。

1025 - 65553

次に、他のピアからの何千ものメッセージをリッスンするときに、事前に定義された既知のポート番号にも送信し、それらを非同期で処理できます。

既知のポート番号 (この場合は 60000) をリッスンするには:

 mySocket.Bind(new IPEndPoint(IPAddress.Any, 60000));

また、各操作の後にソケットを閉じないでください! 開いたままにして再利用してください。

適切に記述されていれば、.Net と OS が要件を処理するために公園を散歩することになります。

于 2013-11-05T01:14:39.710 に答える