Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在数千个端口号上发送/接收UDP数据包_C#_Sockets_Networking_Asynchronous_Udp - Fatal编程技术网

C# 在数千个端口号上发送/接收UDP数据包

C# 在数千个端口号上发送/接收UDP数据包,c#,sockets,networking,asynchronous,udp,C#,Sockets,Networking,Asynchronous,Udp,我对客户机/服务器应用程序有一系列要求,如下所示: 1) 程序向正在侦听预定义UDP端口的主机发送statuscheck消息。此消息通过操作系统提供的源端口号发送 2) 程序需要监听在步骤1中启动的源端口号,以接收来自远程主机的响应。因此,程序必须同时监听数千个端口 3) 每分钟需要对数千台主机执行此过程 下面我创建了一个示例,它向Echo服务器发送大量请求来模拟这种行为。我面临的问题是,尽管我在从远程主机接收数据后关闭了每个套接字,但在大约16000个请求之后,会抛出一个异常,表示系统缺少足够

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

1) 程序向正在侦听预定义UDP端口的主机发送statuscheck消息。此消息通过操作系统提供的源端口号发送

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

3) 每分钟需要对数千台主机执行此过程

下面我创建了一个示例,它向Echo服务器发送大量请求来模拟这种行为。我面临的问题是,尽管我在从远程主机接收数据后关闭了每个套接字,但在大约16000个请求之后,会抛出一个异常,表示系统缺少足够的缓冲区空间或队列已满

实现这些要求的方法是什么

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);
        }
    }
publicsvoidsendchecks()
{
IPEndPoint ip=新的IPEndPoint(IPAddress.Parse(“1.1.1.1”),7);
对于(int i=0;i<200000;i++)
{
Socket _UdpSocket=新套接字(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
stateobject so=新的stateobject(_UdpSocket);
IPEndPoint发送方=新IPEndPoint(IPAddress.Any,0);
端点tempRemoteEP=(端点)发送方;
_UdpSocket.Bind(tempRemoteEP);
string welcome=“Hello”;
字节[]数据=新字节[5];
数据=Encoding.ASCII.GetBytes(欢迎使用);
_UdpSocket.BeginSendTo(数据,0,数据.长度,SocketFlags.None,ip,新的异步回调(OnSend),\u UdpSocket);
//开始收听用户发送的消息
EndPoint newClientEP=新的IPEndPoint(IPAddress.Any,0);
_UdpSocket.BeginReceiveFrom(so.buffer,0,so.buffer.Length,SocketFlags.None,ref newClientEP,new AsyncCallback(DoReceiveFrom),so);
}
}
私人无效或接收自(IAsyncResult ar)
{
尝试
{
stateobject so=(stateobject)ar.AsyncState;
插座s=so.sock;
//创建要传递给EndReceiveFrom的临时端点。
IPEndPoint发送方=新IPEndPoint(IPAddress.Any,0);
端点tempRemoteEP=(端点)发送方;
int read=s.EndReceiveFrom(ar,ref tempRemoteEP);
so.sb.Append(Encoding.ASCII.GetString(so.buffer,0,read))
//所有数据都已读取,因此将其显示到控制台。
字符串结构内容;
strContent=so.sb.ToString();
WriteLine(String.Format(“从套接字“+”数据={1}”读取{0}字节,strContent.Length,strContent));
s、 Close();
s、 处置();
}
捕获(例外情况除外)
{                
控制台写入线(ex);
}
}
私人无效支出(IAsyncResult ira)
{
套接字s=(套接字)ira.AsyncState;
WriteLine(“已将数据发送到端口{0}上的服务器,((IPEndPoint)s.LocalEndPoint).port);
s、 EndSend(ira);
}
}

我认为,就性能和简单性而言,最好的方法是在以下任意位置使用一个端口号:

1025 - 65553
然后,当侦听来自其他对等方的数千条消息时,它们也会发送到预定义的已知端口号,您可以异步处理它们

要侦听已知端口号(在本例中为60000),请执行以下操作:

 mySocket.Bind(new IPEndPoint(IPAddress.Any, 60000));
每次操作后也不要关闭插座!保持打开状态并重复使用


如果写得好,这将是.Net和操作系统处理您的需求的最佳选择。

您正试图以.Net允许的速度发送200000个请求,同时尝试聆听200000个响应。我怀疑操作系统能处理这个问题?考虑到这些要求,你会建议我怎么做?需要多长时间才能发出16000个请求并发生异常?我认为.NET可以以比网络发送更快的速度对它们进行排队,如果发生这种情况,您将以某种方式耗尽资源。如果您对预期的负载类型有一个估计,请在上面限制该测试程序以达到该速率,而不是在尽可能短的时间内完成尽可能多的操作。引发异常需要将近13秒的时间。问题是,当还有更多可用端口时,它为什么会耗尽资源?当异常发生时,系统上有足够的ram。是的,这将是另一种选择。我可以在一个套接字上发送数千个请求并同时侦听。但是考虑到问题的要求,我希望能为我的问题找到一个解决方案。到底什么系统会要求您在每次发送时使用不同的端口号?传统系统往往有特定的要求。看看您的问题,我的答案会符合您的要求-而不是依赖操作系统提供的端口发送发送您指定的端口!远程同行不会介意的!如果您确实想使用随机端口,您仍然可以使用相同的套接字,并在Winsock套接字上使用pinvoke来欺骗源端口。