Broadcasting UDP message to all the available network cards

Anuya picture Anuya · Jul 8, 2009 · Viewed 27.8k times · Source

I need to send a UDP message to specific IP and Port.

Since there are 3 network cards,

10.1.x.x
10.2.x.x
10.4.x.x

when i send a UDP message,i am receiving the message only in one network adapter...the rest of the ip's are not receiving.

I want to check for the network adapter while sending the message. How can I do that?


Currently I am using the following:

IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
UdpClient sendUdpClient = new UdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

Answer

Rex Logan picture Rex Logan · Jul 8, 2009

This is actually trickier than it sounds because if you have more than one interface the broadcasts will not always go out to all the interfaces. To get around this I created this class.

public class MyUdpClient : UdpClient
{
   public MyUdpClient() : base()
   {
      //Calls the protected Client property belonging to the UdpClient base class.
      Socket s = this.Client;
      //Uses the Socket returned by Client to set an option that is not available using UdpClient.
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
   }

   public MyUdpClient(IPEndPoint ipLocalEndPoint) : base(ipLocalEndPoint)
   {
      //Calls the protected Client property belonging to the UdpClient base class.
      Socket s = this.Client;
      //Uses the Socket returned by Client to set an option that is not available using UdpClient.
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
      s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
   }

}

Then to send the UDP packet via broadcast, I use something like the following. I am using IPAddress.Broadcast and MyUdpClient, which is different from your code.

IPEndPoint  localEndPoint  = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint  targetEndPoint = new IPEndPoint(IPAddress.Broadcast, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

Also, you should note that when you use a specific ipaddress instead of broadcast the route table only sends it out the interface that matches the address.

So in your example, unicast is used. You need to set LocalIP to the IP of the local interface you want to send out to. With three interfaces, you would have three local IP's and you need to pick the correct one to use.

IPEndPoint  localEndPoint  = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint  targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

Because route is turned off you might see it on all interfaces but you will need to test this for the unicast case.

If you don't care about the send IP or port you can use the following code.

IPEndPoint  targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient();
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

or for broadcast

IPEndPoint  targetEndPoint = new IPEndPoint(IPAddress.Broadcast, iTargetPort);
MyUdpClient sendUdpClient  = new MyUdpClient();
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

The problem with IPAddress.Broadcast is that they will not route through any gateways. To get around this you can create a list of IPAddresses and then loop through and send. Also since Send can fail for network issues that you cannot control you should also have a try/catch block.

ArrayList ip_addr_acq = new ArrayList();

ip_addr_acq.Add(IPAddress.Parse("10.1.1.1")); // add to list of address to send to

try
{
   foreach (IPAddress curAdd in ip_addr_acq) 
   {
       IPEndPoint  targetEndPoint = new IPEndPoint(curAdd , iTargetPort);
       MyUdpClient sendUdpClient  = new MyUdpClient();
       int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);

       Thread.Sleep(40); //small delay between each message
    }
 }
 catch
 {
 // handle any exceptions
 }

Edit: see above change to unicast with multiple interfaces and also Problem Trying to unicast packets to available networks.