Broadcasting UDP message to all the available network cards
Asked Answered
O

4

15

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);
Ophthalmoscopy answered 8/7, 2009 at 4:40 Comment(6)
Can you clarify more what you are want trying to-do.Dwaindwaine
My application will send messages to an application in 10+ systems. In which all the systems are in three differnt network cards. Like 10.1.x.x / 10.2.x.x / 10.4.x.x I am able to receive the message in only one network card 10.1.x.x but not in other two network cards. So i want to check the avaiablity of network card and then send the message. Thanks.Ophthalmoscopy
so is the message have just to check network availability, or does it have some other payload/meaning?Dwaindwaine
If you are trying to get redundancy, for the case where the send is connected to Network A, but receiver is disconnected to A but connected to B and C (due to network card/cable failure), and you want your message to arrive at the receiver then sending it like Rex says should do the trick, but you'll have to manage the duplicate and maybe out of order handling at the receiving end.Dwaindwaine
If you are purely want to test connectivity of each host of all networks, send a unicast message to the network address of the host on each network A,B and C.Dwaindwaine
when i tried to network adapter A, it works fine. when i tried to network adapter B, error : A Socket operation was attempted to an unreacheable host. when i tried to network adapter C, error : A Socket operation was attempted to an unreacheable host.Ophthalmoscopy
U
18

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.

Udela answered 8/7, 2009 at 5:11 Comment(5)
Hi Rex Logan, when i tried ur code, i am getting the following error : A Socket operation was attempted to an unreacheable host. I am confused here, the network adapter with that IP exists. when i debugged the below line... int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint); i saw targetEndPoint = {10.4.1.2:1982}. when the targetEndPoint is {10.1.1.1:1982} i am receiving the packet in remote machine. :(Ophthalmoscopy
What happens if you send to IPAddress.Broadcast? You might try the simplified versions I added as well.Udela
You also might try commenting out s.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.DontRoute, 1); or s.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.Broadcast, 1) to see what happensUdela
Its the same. could find that IP. I tried to ping 10.4.1.2 but it is says "Destination host unreachable". So now it is a network problem or still applicaiton problem ? Thanks.Ophthalmoscopy
when i do ipaddress.broadcast, i am not receing the packet in remote machine.Ophthalmoscopy
B
4

Expansion of Rex's Answer. This allows you to not have to hard code the ip addresses that you want to broadcast on. Loops through all interfaces, checks if they are up, makes sure it has IPv4 information, and an IPv4 address is associated with it. Just change the "data" variable to whatever data you want to broadcast, and the "target" port to the one you want. Small drawback is that if an interface has multiple ip addresses associated with it, it will broadcast out of each address. Note: this will ALSO try to send broadcasts through any VPN adapter (via Network and Sharing Center/Network Connections, Win 7+ verified), and if you want to receive responses, you will have to save all the clients. You also will not need a secondary class.

    foreach( NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces() ) {
        if( ni.OperationalStatus == OperationalStatus.Up && ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() != null ) {
            int id = ni.GetIPProperties().GetIPv4Properties().Index;
            if( NetworkInterface.LoopbackInterfaceIndex != id ) {
                foreach(UnicastIPAddressInformation uip in ni.GetIPProperties().UnicastAddresses ) {
                    if( uip.Address.AddressFamily == AddressFamily.InterNetwork ) {
                        IPEndPoint local = new IPEndPoint(uip.Address.Address, 0);
                        UdpClient udpc = new UdpClient(local);
                        udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
                        udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
                        byte[] data = new byte[10]{1,2,3,4,5,6,7,8,9,10};
                        IPEndPoint target = new IPEndPoint(IPAddress.Broadcast, 48888);
                        udpc.Send(data,data.Length, target);
                    }
                }
            }
        }
    }
Borborygmus answered 25/9, 2016 at 19:42 Comment(0)
B
4

I solved this problem by sending the UDP broadcast from each adapter (using bind):

public static void SNCT_SendBroadcast(out List<MyDevice> DevicesList)
{
DevicesList = new List<MyDevice>();
byte[] data = new byte[2]; //broadcast data
data[0] = 0x0A;
data[1] = 0x60;

IPEndPoint ip = new IPEndPoint(IPAddress.Broadcast, 45000); //braodcast IP address, and corresponding port

NetworkInterface[] nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); //get all network interfaces of the computer

foreach (NetworkInterface adapter in nics)
{
// Only select interfaces that are Ethernet type and support IPv4 (important to minimize waiting time)
if (adapter.NetworkInterfaceType != NetworkInterfaceType.Ethernet) { continue; }
if (adapter.Supports(NetworkInterfaceComponent.IPv4) == false) { continue; }
try
{
    IPInterfaceProperties adapterProperties = adapter.GetIPProperties();    
    foreach (var ua in adapterProperties.UnicastAddresses)
    {
        if (ua.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
        {
         //SEND BROADCAST IN THE ADAPTER
            //1) Set the socket as UDP Client
            Socket bcSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //broadcast socket
            //2) Set socker options
            bcSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            bcSocket.ReceiveTimeout = 200; //receive timout 200ms
            //3) Bind to the current selected adapter
            IPEndPoint myLocalEndPoint = new IPEndPoint(ua.Address, 45000);
            bcSocket.Bind(myLocalEndPoint);
            //4) Send the broadcast data
            bcSocket.SendTo(data, ip);

        //RECEIVE BROADCAST IN THE ADAPTER
            int BUFFER_SIZE_ANSWER = 1024;
            byte[] bufferAnswer = new byte[BUFFER_SIZE_ANSWER];
            do
            {
                try
                {
                    bcSocket.Receive(bufferAnswer);
                    DevicesList.Add(GetMyDevice(bufferAnswer)); //Corresponding functions to get the devices information. Depends on the application.
                }
                catch { break; }

            } while (bcSocket.ReceiveTimeout != 0); //fixed receive timeout for each adapter that supports our broadcast
            bcSocket.Close();
        }
    }
  }
  catch { }
}
return;
}
Bambibambie answered 19/6, 2017 at 7:1 Comment(1)
With some slight modification this worked well for my needs, thanks! 1) you will need to move the outer Try/Catch block inside the ForEach UnicastAddr and add a finally block to dispose of the bcSocket obj as the the binds will throw in some circumstances. 2) Qualifying on NetworkInterfaceType.Ethernet only will ignore some common hardware like Wireless cards/etc. (NetworkInterfaceType.Wireless80211)Bree
D
1

If you are sending to a specific IP address then you are unicasting, not broadcasting.

Dwaindwaine answered 8/7, 2009 at 4:46 Comment(4)
Oh yeah thats right. But i shud select the network before sending right ?Ophthalmoscopy
Ah you trying to send a packet out each local network card to a remote host with a single network card? If your try to test each network card, find a host on that network to send a message to. Let the OS do the routing for you.Dwaindwaine
But the OS is always routing to the first network card 10.1.x.xOphthalmoscopy
If you want to send out different Nic's send to the different addresses of the hosts. That is if they are all on three networks. It comes down to what you are try to achieve, testing the network connectivity, or send an actual higher layer message.Dwaindwaine

© 2022 - 2024 — McMap. All rights reserved.