Why are my UDP multicast not reaching machines on the network?

北战南征 提交于 2019-12-03 21:38:21

So the issue turned out to be that as I had more than 1 active network connection it was choosing one and using that and that was causing the UDP packets to be sent out on a different network connection that the client was listening on. As i had installed Virtual box it had installed and activated the VirtualBox Host-only network adapter, so that host only network connections could be supported. When I switched VirtualBox over to host only mode the packets started to be received. Disabling the VirtualBox adapter and switching back to a bridged connection also worked.

If you have multiple interfaces, the right answer is to listen to all of them, and not try to pick one if you do not have a definition of what is right.

Here's how I implemented a UDP discovery service. It broke, originally, because my Virtual Box interfaces got in the way and swallowed up the UDP broadcasts on a random IP subnet (192.168.56.x) instead of my actual ethernet connection (192.168.0.x). So I improved it, based on the answer from Guge. It's a little verbose and I probably didn't code it in the most neat way, but it works now. I broadcast on all interfaces, then receive the data (round-robin) on all interfaces until the timeout, or single response (if justFindOne = true).

For some reason, IPv6 interfaces crash the UDP part, so I just filter out IPv4 addresses. Please correct me if there is a way for this to work on both.

    const int iPort = 7611;
    const int IP_TIMEOUT = 1000;

    private static List<DiscoveryServer> FindIPAddresses(string filter, bool justFindOne)
    {
        List<DiscoveryServer> ipNames = new List<DiscoveryServer>();

        byte[] message = new byte[2] { 17, 2 };
        string hostname = Dns.GetHostName();
        IPHostEntry entry = Dns.GetHostEntry(hostname);
        List<UdpClient> clients = new List<UdpClient>();

        try
        {
            // send out UDP packets on all IPv4 interfaces.

            foreach (var ipAddress in entry.AddressList)
            {
                if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
                {
                    IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, iPort);

                    UdpClient udpC = new UdpClient(ipLocalEndPoint);
                    clients.Add(udpC);
                    udpC.EnableBroadcast = true;
                    udpC.Client.ReceiveTimeout = IP_TIMEOUT;
                    int response1 = udpC.Send(message, 2, new IPEndPoint(IPAddress.Broadcast, iPort));
                }
            }

            if (clients.Count == 0)
            {
                throw new Exception("There are no IPv4 network interfaces available");
            }

            System.DateTime startTime = System.DateTime.Now;
            double timeout = IP_TIMEOUT / 1000;

            IPEndPoint remEP = new IPEndPoint(IPAddress.Broadcast, iPort);

            while (System.DateTime.Now.Subtract(startTime) < TimeSpan.FromSeconds(timeout) &&
                !(justFindOne && ipNames.Count() > 0))
            {
                foreach (var udpC in clients)
                {
                    if (udpC.Available > 0)
                    {
                        byte[] response = udpC.Receive(ref remEP);
                        string name;
                        if (response.Length > 2)
                        {
                            name = System.Text.Encoding.ASCII.GetString(response, 3, response[2]);
                            if (filter == "" || name.Contains(filter))
                            {
                                DiscoveryServer ds = new DiscoveryServer(name, remEP.Address);
                                ipNames.Add(ds);
                                if (justFindOne) break;
                            }
                        }
                    }
                }
            }
        }
        finally
        {
            foreach (var udpC in clients)
            {
                udpC.Close();
            }
        }
        return ipNames;

    }

I'd try Wireshark.

Guge

There are a few issues to look into here.

The first is: are you sure multicast is the best way of doing this? I think broadcast would serve you better.

The other is: routers generally don't forward multicast or broadcast, switches and hubs do.

Take a look at the following two questions: Why are (UDP multicast) packets not being received? and UDP Multicast over the internet?

EDIT:

When you create your UdpClient you can specify which local endpoint you will be sending from. http://msdn.microsoft.com/en-us/library/k227d11f.aspx

Alan Beard

In your code, you do not setup the TTL for your call to UdpClient. So if the default TTL is 1, then your packets won't get past the first router.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!