Gahken
Gahken

Reputation: 1

Multiple UDP connections to different remote IPs with the same port

I have a need to talk to multiple devices on a private LAN using a proprietary UDP protocol. In a production setting we have a industrial PC running a C++ application that can connect to multiple devices and communicate freely with them. I am trying to duplicate that communication using C# for a windows application that technicians, testers and others would be using. I have probably done this myself a thousands times in c++ but c# seems to be giving me all sorts of fits.

I have one UDP listener listening on Any IP and specific Port. This port is different from the device command port. This receives a periodic heartbeat from each device. From this communication I am able to get the specific IP and command Port for that device. The program maintains a list of devices and displays that lists to the user. The user can then select a specific device and inspect it more for more details.

If there are several devices with the same port number the program will not be able to inspect those devices at the same time. When the user selects the device the program creates a new instance of the UdpClient. In pseudo-code form:

udpConnection = new UdpClient();
udpConnection.ExclusiveAddressUse = false;
udpConnection.Client.SetSocketOption(SocketOptionLevel.Socket,  SocketOptionName.ReuseAddress, true);
udpConnection.Client.Bind(localEndpoint);
udpConnection.Client.Connect(remoteEndpoint);

Local Endpoint is the Local interface IP and the Device Port Number of the machine the application is running on. Remote EndPoint is the Device IP and Device Port that the application wants to inspect further.

As anyone had similar issues and what have you done to get around it?

Thanks in advance

Update sample network diagram and further explanation: Network Diagram

In the image I will be able to have two windows viewing Device A and C or B and C simultaneously with no issues. However if I have Device A and C the window that I opened second will not get any communications updates until I close the first window. If I "sniff" the network with WireShark I see all the communications as I would expect.

Code Snippet:

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);
  }
}

Upvotes: 0

Views: 2465

Answers (1)

Gabriel Luci
Gabriel Luci

Reputation: 40928

I think your problem is here:

udpConnection.Client.Bind(localEndpoint);

This line, if I understand correctly, is telling it to use the same local port to make the outbound request. But you already have another UdpClient listening on that port, so Windows won't know which one to send the traffic to (or it just sends it to the first one).

You should be able to just not use Bind() here. Without it, when you call Connect(), it will assign a random local port, which is the way most outbound network requests work.

Or if you need to specify the network interface, then pass 0 for the port and Windows will assign one:

localEndpoint = new IPEndPoint(ipAddress, 0);

Upvotes: 2

Related Questions