具有相同端口的多个UDP连接到不同的远程IP

时间:2018-11-28 01:57:31

标签: c# udpclient

我需要使用专用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);
  }
}

1 个答案:

答案 0 :(得分:1)

我认为您的问题在这里:

udpConnection.Client.Bind(localEndpoint);

如果我正确理解的话,这行告诉它使用相同的本地端口发出出站请求。但是您已经在该端口上监听了另外一个UdpClient,因此Windows将不知道将流量发送到哪个端口(或者只是将其发送到第一个)。

您应该只能在这里不使用Bind()。没有它,当您呼叫Connect()时,它将分配一个随机的本地端口,这是大多数出站网络请求的工作方式。

或者,如果您需要指定网络接口,则为该端口传递0,Windows将分配一个:

localEndpoint = new IPEndPoint(ipAddress, 0);