c# - 多个 UDP 连接到具有相同端口的不同远程 IP
问题描述
我需要使用专有 UDP 协议与专用 LAN 上的多个设备通信。在生产环境中,我们有一台运行 C++ 应用程序的工业 PC,它可以连接到多个设备并与它们自由通信。我正在尝试使用 C# 为技术人员、测试人员和其他人将使用的 Windows 应用程序复制该通信。我自己可能已经在 C++ 中做了数千次,但 C# 似乎给了我各种各样的配合。
我有一个侦听任何 IP 和特定端口的 UDP 侦听器。此端口不同于设备命令端口。这会接收来自每个设备的周期性心跳。通过这种通信,我可以获得该设备的特定 IP 和命令端口。该程序维护设备列表并向用户显示该列表。然后,用户可以选择特定设备并对其进行更多检查以获取更多详细信息。
如果有多个设备具有相同的端口号,程序将无法同时检查这些设备。当用户选择设备时,程序会创建一个新的 UdpClient 实例。以伪代码形式:
udpConnection = new UdpClient();
udpConnection.ExclusiveAddressUse = false;
udpConnection.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpConnection.Client.Bind(localEndpoint);
udpConnection.Client.Connect(remoteEndpoint);
本地端点是运行应用程序的机器的本地接口 IP 和设备端口号。远程端点是应用程序想要进一步检查的设备 IP 和设备端口。
任何人都有类似的问题,你做了什么来解决它?
提前致谢
更新示例网络图和进一步解释: 网络图
在图像中,我将能够有两个窗口同时查看设备 A 和 C 或 B 和 C,没有问题。但是,如果我有设备 A 和 C,那么在我关闭第一个窗口之前,我第二个打开的窗口不会获得任何通信更新。如果我用 WireShark “嗅探”网络,我会看到所有通信,如我所料。
代码片段:
private void ClientThread()
{
IPEndPoint myEndPoint;
myLogger = LogManager.GetLogger("ClientLogs");
myLogger.Debug("Client Started!");
IPAddress ClientAddress = System.Net.IPAddress.Parse(ClientIP);
myIP = "10.0.0.4"; // Currently hard-coded local interface IP
IPAddress thisAddress = System.Net.IPAddress.Parse(myIP);
ClientEndPoint = new IPEndPoint(ClientAddress, Convert.ToInt32(ClientPort));
myEndPoint = new IPEndPoint(thisAddress, Convert.ToInt32(ClientPort)); // Both forms launch but only the first one will receive data.
//myEndPoint = new IPEndPoint(thisAddress, 0); // Both forms will launch but no data received (packets do show being received in wireshark)
//myEndPoint = new IPEndPoint(IPAddress.Any, ClientPort); // Both forms launch but only the first one will receive data.
try
{
myUDP = new UdpClient();
myUDP.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // "Only one usage of each socket address (protocol/network address/port) is normally permitted" Exception when removed.
myUDP.ExclusiveAddressUse = false; // No difference if this is removed
myUDP.Client.Bind(myEndPoint); // Neither form will receive data if this is removed
myUDP.Client.Connect(ClientEndPoint); // removing this will allow the forms to launch but again the only the first will receive data
}
catch (Exception ex)
{
myUDP = null;
myLogger.Fatal(String.Format("Error in setting up UDP Client: {0}", ex.Message));
return;
}
myLogger.Debug(String.Format("Attempt to connect to : {0} on {1}", ClientIP, Convert.ToInt32(ClientPort)));
byte[] bytes = new byte[1452];
try
{
while (ThreadLoop)
{
IPEndPoint newEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = myUDP.Receive(ref newEndPoint);
ParseProtocolPacket(ref receiveBytes); // Code to parse the data received
}
}
catch (Exception Ex)
{
myLogger.Debug("Client Socket Other Error: " + Ex.Message);
}
}
解决方案
我认为你的问题在这里:
udpConnection.Client.Bind(localEndpoint);
如果我理解正确,这条线告诉它使用相同的本地端口来发出出站请求。但是您已经UdpClient
在该端口上进行了另一个侦听,因此 Windows 将不知道将流量发送到哪个端口(或者它只是将其发送到第一个端口)。
你应该可以不在Bind()
这里使用。没有它,当您调用 时Connect()
,它将分配一个随机的本地端口,这是大多数出站网络请求的工作方式。
或者,如果您需要指定网络接口,则传递0
端口,Windows 将分配一个:
localEndpoint = new IPEndPoint(ipAddress, 0);
推荐阅读
- php - wordpress 消耗大量 CPU
- javascript - TinyMCE .filter() 不是提到的功能(Laravel)
- python - ValueError:发现样本数量不一致[1691、725]
- php - 我不明白为什么 get_class_vars() 在 php 7 和 codeigniter 4 中不起作用
- sql - SQL sum 除以日期计数
- jsp - 如何使用 jdbc 连接到 oracle
- php - 将 php 开关链接到 html php 页面
- css - Weasyprint 打印损坏的 pdf
- javascript - mmenu js API - 菜单未显示
- c++ - 在 C++ 中的 SDL2 和 OpenGL2 中将 rgb 像素阵列绘制或 blit 到窗口的最快方法