UDP 客户端 - 接收排队的数据包
UDP Client - Reception of enqueued packets
我正在开发 UDP 客户端 PC 应用程序。它应该从超过 4 个设备接收 UDP 数据报。
系统的行为如下:
- 多台设备通过固定端口 (11000) 上的 UDP 广播相互通信,形成没有连接到 Internet 的个域网。
- PC 应用程序在连接到同一网络的计算机上执行。
- PC 应用程序在 11000 端口上侦听 UDP 广播以发现设备。
- 当从 PC 应用程序接收到特定命令时,该设备进入不同的执行模式,而其他设备继续广播它们的数据包。
- 当个人区域网络中只有一台设备时,这会以所需的方式运行。
当网络中有两个或更多设备时,我遇到了一个奇怪的问题,例如:
- 我使用发现的设备列表将
endPoint
设置为所需设备的所需 IP 地址和端口。
- 我调用
myUDP.Receive(ref endPoint);
接收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
我正在开发 UDP 客户端 PC 应用程序。它应该从超过 4 个设备接收 UDP 数据报。
系统的行为如下:
- 多台设备通过固定端口 (11000) 上的 UDP 广播相互通信,形成没有连接到 Internet 的个域网。
- PC 应用程序在连接到同一网络的计算机上执行。
- PC 应用程序在 11000 端口上侦听 UDP 广播以发现设备。
- 当从 PC 应用程序接收到特定命令时,该设备进入不同的执行模式,而其他设备继续广播它们的数据包。
- 当个人区域网络中只有一台设备时,这会以所需的方式运行。
当网络中有两个或更多设备时,我遇到了一个奇怪的问题,例如:
- 我使用发现的设备列表将
endPoint
设置为所需设备的所需 IP 地址和端口。 - 我调用
myUDP.Receive(ref endPoint);
接收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