簡體   English   中英

在數千個端口號上發送/接收UDP數據包

[英]Sending/receiving UDP packets on thousands of port numbers

我對客戶端/服務器應用程序有一組要求,如下所示:

1)程序向正在偵聽預定義UDP端口的主機發送狀態檢查消息。 該消息在操作系統給定的源端口號上發送。

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

我認為,就性能和簡單性而言,最好的方法是在以下位置之間的任何位置簡單地使用單個端口號:

1025 - 65553

然后,當偵聽來自其他對等方的數千條消息時,它們還會發送到預定義的已知端口號,您可以異步處理它們。

要收聽已知的端口號,在這種情況下為60000:

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

也不要在每次操作后關閉插座! 保持打開狀態並重新使用它。

正確編寫后,它將可以在.Net和OS的公園中漫步,從而滿足您的需求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM