UDP 客户端 - 接收排队的数据包

UDP Client - Reception of enqueued packets

我正在开发 UDP 客户端 PC 应用程序。它应该从超过 4 个设备接收 UDP 数据报。
系统的行为如下:

当网络中有两个或更多设备时,我遇到了一个奇怪的问题,例如:

此 returns 与网络中第二个设备广播的数据报有关,而不是从我尝试与之通信的设备返回响应。我已经使用 Wireshark 验证了响应是从设备发送的。

我尝试循环有限次数以获得所需的数据报。

// Some code which initializes the endPoint with desired IP Address and Port
...
// Some code which sends the data
...
// Some code which sets the IP Address of the device from which the response is expected
selectedIPAddress = IPAddress.Parse(labelIPAddressSettings.Text.Trim());
copyendPoint = endPoint;
// Listen to response
do
{
    rexdDatagram = myUDP.Receive(ref endPoint);
    if (endPoint.Address != selectedIPAddress)
    {
        // This datagram is not from the desired device
        // Restore to the desired endpoint
        endPoint = copyendPoint;
        // Not sure if there is way to discard this enqueued datagram
    }
    
    i_timeout = i_timeout + 1;
    if (i_timeout == 10)
    {
        // Datagram from the desired device has not been received 
        break;
    }
    // Not sure if the thread needs to sleep, debugging..
    Thread.Sleep(1000);
} while (1);

问题: 我的代码在排队的数据报中循环是否正确?有没有办法丢弃以前的数据报并重新开始?

方法 UdpClient.Receive 上的参数 remoteEP 不是指定从哪个远程端点接收数据,而是指定哪个远程端点发送数据。您不能有选择地仅从特定端点接收。

相反,您必须从每个人那里接收所有内容,并丢弃不是从您想要的远程端点发送的包。您可以这样做:

byte[] receivedData = null;
var attempts = 0;

while (attempts < 10)
{
    var recvEp = new IPEndPoint(IPAddress.Any, 0);
    readData = myUDP.Receive(ref recvEp);
  
    if (recvEp.Address == selectedIPAddress)
    {
       // We received data from the correct remote source
       receivedData = readData;
       break;
    }

    attempts++;
}

此代码将从任何地方接收数据,如果在 10 次尝试内未从正确的端点接收数据,它将停止。导致 receivedData 为空。

您可能希望将您的代码转换为等待一定数量的 时间 而不是一定数量的尝试,以增加实际收到某些东西的机会。可以这样做:

var start = DateTime.Now;
byte[] receivedData = null;

while((DateTime.Now - start).TotalSeconds < 10)
{
    var recvEp = new IPEndPoint(IPAddress.Any, 0);
    readData = myUDP.Receive(ref recvEp);
  
    if (recvEp.Address == selectedIPAddress)
    {
       // We received data from the correct remote source
       receivedData = readData;
       break;
    }
}

此代码将尝试 10 秒,如果未收到任何消息,将在 10 秒后停止。这不是完全干净的代码,例如,如果你愿意,你可以让整个事情异步。


注意: 这两个代码片段可能会导致无限循环,因为只要没有任何传入数据,myUDP.Receive(ref recvEp) 就会阻塞。因此,如果您所有的远程端点同时决定停止发送数据,则接收呼叫将永远不会 return