首页 > 解决方案 > 多个 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);
  }
}

标签: c#udpclient

解决方案


我认为你的问题在这里:

udpConnection.Client.Bind(localEndpoint);

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

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

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

localEndpoint = new IPEndPoint(ipAddress, 0);

推荐阅读