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



我正在开发一个UDP客户端PC应用程序。它应该接收来自4个以上设备的UDP数据报
系统的行为方式如下:

  • 多个设备通过固定端口(11000(上的UDP广播相互通信,形成一个无法连接到互联网的个人区域网络
  • PC应用程序在连接到同一网络的计算机上执行
  • PC应用程序在11000端口上侦听UDP广播以发现设备
  • 当从PC应用程序接收到特定命令时,该设备进入不同的执行模式,而其他设备继续广播其数据包
  • 当个人区域网络中只有一个设备时,这以期望的方式表现

当网络中有两个或多个设备时,我面临一个奇怪的问题,例如:

  • 我使用发现的设备列表将endPoint设置为所需设备的所需IPAddress和Port
  • 我调用myUDP.Receive(ref endPoint);接收UDP数据报

这将返回由网络中的第二个设备广播的数据报,而不是返回我试图与之通信的设备的响应。我已经使用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)就会阻塞。因此,如果所有远程端点决定同时停止发送数据,则接收呼叫将永远不会返回

最新更新