UDP: Read data from all network interfaces

J4N picture J4N · Mar 7, 2013 · Viewed 10.8k times · Source

I've the following code to read multicast message coming from the network, for a specified IP+Port

private static void ReceiveMessages(int port, string ip, CancellationToken token)
{
    Task.Factory.StartNew(() =>
        {
            using (var mUdpClientReceiver = new UdpClient())
            {
                var mReceivingEndPoint = new IPEndPoint(IPAddress.Any, port);
                mUdpClientReceiver.ExclusiveAddressUse = false;
                mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                mUdpClientReceiver.ExclusiveAddressUse = false;
                mUdpClientReceiver.Client.Bind(mReceivingEndPoint);
                mUdpClientReceiver.JoinMulticastGroup(IPAddress.Parse(ip), 255);

                while (!token.IsCancellationRequested)
                {
                    byte[] receive = mUdpClientReceiver.Receive(ref mReceivingEndPoint);

                    Console.WriteLine("Message received from {0} ",mReceivingEndPoint);
                }
            }
        });
}

I've two network adapter from which I've data coming on this multicast ip+port(confirmed by two instances of wireshark monitoring each network adapter). I see on wireshark a lot of traffic coming on those port+Ip) for both network cards.

The problem is that on my console, I only see messages coming from one network card.

I double checked with netstat, I don't have any other software listening on my port: enter image description here

So why am I getting traffic from only one of my two network cards?

EDIT:

I even tried the following:

private static void ReceiveMessages(int port, string ip, CancellationToken token, IEnumerable<IPAddress> ipAddresses)
{
    foreach (IPAddress ipAddress in ipAddresses)
    {
        IPAddress ipToUse = ipAddress;
        Task.Factory.StartNew(() =>
        {
            using (var mUdpClientReceiver = new UdpClient())
            {

                var mReceivingEndPoint = new IPEndPoint(ipToUse, port);
                mUdpClientReceiver.ExclusiveAddressUse = false;
                mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
                mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
                mUdpClientReceiver.ExclusiveAddressUse = false;
                mUdpClientReceiver.Client.Bind(mReceivingEndPoint);
                mUdpClientReceiver.JoinMulticastGroup(IPAddress.Parse(ip), 255);
                Console.WriteLine("Starting to listen on "+ipToUse);
                while (!token.IsCancellationRequested)
                {
                    byte[] receive = mUdpClientReceiver.Receive(ref mReceivingEndPoint);

                    Console.WriteLine("Message received from {0} on {1}",  mReceivingEndPoint,ipToUse);
                }
            }
        });
    }
}

I see the "Starting to listen on theCorrectIP" twice(for my two IPs), but it still display only data coming from one network card.

EDIT 2

I did notice something else that is strange too. If I disable the interface on which I receive all data, and then start the software, I now get data from the other interface. If I activate again the interface and restart the software, I still get the traffic on the non-deactivated card.

And I know for sure that I've devices that respond to me, that are connected only to one network(not both)

EDIT 3

Another thing: if I send a message from me(localhost), on all network card that I've, I see them coming on my two network interfaces. BUT, if I start my program twice, only the first programm get messages, not the second one.

Edit 4

Additional info, following the first comment: I've two ethernet cards, one with the 10.10.24.78 ip, the other with the 10.9.10.234 ip. It's not me that send data, but network pieces(the port 5353 with this ip is a know multicast address used for mDNS, so I should receive traffic from things like printer, itunes, macs, and some other pieces of software we created). Data are multicasted on the ip 224.0.0.251 and port 5353.

Here is a code that you could use to send data on severals IPs, but like I described, if you start it in local it almost works(except that only one local client receive the message).

private static void SendManuallyOnAllCards(int port, string multicastAddress, IEnumerable<IPAddress> ipAddresses)
{
    foreach (IPAddress remoteAddress in ipAddresses)
    {
        IPAddress ipToUse = remoteAddress;
        using (var mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
        {
            mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
                                        new MulticastOption(IPAddress.Parse(multicastAddress)));
            mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
            mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

            var ipep = new IPEndPoint(ipToUse, port);
            //IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(multicastAddress), port);
            mSendSocket.Bind(ipep);
            mSendSocket.Connect(ipep);


            byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
            mSendSocket.Send(bytes, bytes.Length, SocketFlags.None);
        }
    }
}

EDIT 5 Here is the result of my route print(Didn't know that command), and on my two IPs, I always receive data on the 10.9.10.234 enter image description here

Edit 6

I tried several other things:

  1. Use a socket to receive instead of the UdpClient --> Didn't worked
  2. Set some addition socketOption on the reader(DontRoute =1, Broadcast=1) -->Didn't worked
  3. Specify the MulticastInterface that the reader Socket has to use(using socketOption MulticastInterface) --> Didn't work

Answer

floppes picture floppes · Apr 4, 2013

I had the same problem that I wanted to receive multicasts from all my network interfaces. As EJP already said, you need to call JoinMulticastGroup(IPAddress multicastAddr, IPAddress localAddress) on the UdpClient for all network interfaces:

int port = 1036;
IPAddress multicastAddress = IPAddress.Parse("239.192.1.12");

client = new UdpClient(new IPEndPoint(IPAddress.Any, port));

// list of UdpClients to send multicasts
List<UdpClient> sendClients = new List<UdpClient>();

// join multicast group on all available network interfaces
NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

foreach (NetworkInterface networkInterface in networkInterfaces)
{
    if ((!networkInterface.Supports(NetworkInterfaceComponent.IPv4)) ||
        (networkInterface.OperationalStatus != OperationalStatus.Up))
    {
        continue;
    }

    IPInterfaceProperties adapterProperties = networkInterface.GetIPProperties();
    UnicastIPAddressInformationCollection unicastIPAddresses = adapterProperties.UnicastAddresses;
    IPAddress ipAddress = null;

    foreach (UnicastIPAddressInformation unicastIPAddress in unicastIPAddresses)
    {
        if (unicastIPAddress.Address.AddressFamily != AddressFamily.InterNetwork)
        {
            continue;
        }

        ipAddress = unicastIPAddress.Address;
        break;
    }

    if (ipAddress == null)
    {
        continue;
    }

    client.JoinMulticastGroup(multicastAddress, ipAddress);

    UdpClient sendClient = new UdpClient(new IPEndPoint(ipAddress, port));
    sendClients.Add(sendClient);
}

I am also creating a list of UdpClients so I can send my multicasts on all network interfaces.