0

我对客户端/服务器应用程序有一组要求,如下所示:

1) 程序向正在侦听预定义 UDP 端口的主机发送状态检查消息。此消息在 OS 给定的源端口号上发送。

2)程序需要监听步骤1中发起的源端口号来接收远程主机的响应。因此程序必须同时监听数千个端口。

3)这个过程需要为每分钟数千台主机完成

下面我创建了一个示例示例,它向 Echo 服务器发送大量请求以模仿这种行为。我面临的问题是,虽然我在从远程主机接收数据后关闭了每个套接字,但在大约 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 和操作系统处理您的要求的公园。

于 2013-11-05T01:14:39.710 回答