我需要使用专用UDP协议与专用LAN上的多个设备进行通讯。在生产环境中,我们有一台运行C ++应用程序的工业PC,它可以连接到多个设备并与它们自由通信。我正在尝试使用C#为技术人员,测试人员和其他人正在使用的Windows应用程序复制该通信。我自己可能已经在c ++中完成了数千次,但是c#似乎给了我各种各样的机会。
我有一个UDP侦听器,用于侦听任何IP和特定端口。该端口不同于设备命令端口。这会从每个设备接收定期的心跳。通过这种通信,我可以获取该设备的特定IP和命令端口。该程序维护设备列表并向用户显示该列表。然后,用户可以选择一个特定的设备,并对其进行更多检查以了解更多详细信息。
如果有多个具有相同端口号的设备,则程序将无法同时检查这些设备。当用户选择设备时,程序将创建UdpClient的新实例。以伪代码形式:
udpConnection = new UdpClient();
udpConnection.ExclusiveAddressUse = false;
udpConnection.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpConnection.Client.Bind(localEndpoint);
udpConnection.Client.Connect(remoteEndpoint);
Local Endpoint是运行应用程序的计算机的本地接口IP和设备端口号。远程端点是应用程序要进一步检查的设备IP和设备端口。
任何人都有类似的问题,您为解决该问题做了什么?
预先感谢
更新示例网络图和进一步的说明: Network Diagram
在图像中,我将能够拥有两个窗口,同时查看设备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);
}
}
答案 0 :(得分:1)
我认为您的问题在这里:
udpConnection.Client.Bind(localEndpoint);
如果我正确理解的话,这行告诉它使用相同的本地端口发出出站请求。但是您已经在该端口上监听了另外一个UdpClient
,因此Windows将不知道将流量发送到哪个端口(或者只是将其发送到第一个)。
您应该只能在这里不使用Bind()
。没有它,当您呼叫Connect()
时,它将分配一个随机的本地端口,这是大多数出站网络请求的工作方式。
或者,如果您需要指定网络接口,则为该端口传递0
,Windows将分配一个:
localEndpoint = new IPEndPoint(ipAddress, 0);