0

I am aware that not all devices respond to ICMP or pings, so the most suitable way to go seems to send an ARP Request to all the IPs possible on LAN, from 192.168.0.0 to 192.168.255.255, but that means requesting over 65000 IPs and it takes a hell lot of time. I want to find another instance of my program in order to sync their contents, but I am not satisfied with the ARP method. So far I've found these nice piece of code here in SO:

[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);

static void Main(string[] args)
{
    List<IPAddress> ipAddressList = new List<IPAddress>();

    for (int i = 0; i <= 255; i++)
    {
        for (int s = 0; s <= 255; s++)
        {
            ipAddressList.Add(IPAddress.Parse("192.168." + i + "." + s));
        }
    }

    foreach (IPAddress ip in ipAddressList)
    {
        Thread thread = new Thread(() => SendArpRequest(ip));
        thread.Start();

    }
}

static void SendArpRequest(IPAddress dst)
{
    byte[] macAddr = new byte[6];
    uint macAddrLen = (uint)macAddr.Length;
    int uintAddress = BitConverter.ToInt32(dst.GetAddressBytes(), 0);

    if (SendARP(uintAddress, 0, macAddr, ref macAddrLen) == 0)
    {
        Console.WriteLine("{0} responded to ping", dst.ToString());
    }
}

but as you can see, ARP Requesting all that range would take a long time. 10 to 15 minutes on my Laptop. Of course, in most cases you would find the desired IP a lot faster, I mean it's not that you are going to be so unlucky that a PC would fall on 192.168.255.255 or so, but still, it takes some minutes. This would only be done just one time, as most of the time PCs and Laptops use preferred IPs that would be kept for days or months unless changed, so as long as it keeps working on that IP, another ARP fetching won't be needed. So far the best option is to have this "Hot start" happen for the first time and decorate it with a loading screen, but I'd like to know if there's a much more faster way to achieve this. Also, I'm only looking for Windows PCs since it's just between instances of the same app.

Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123
  • Can't you just have your network person give you the DHCP lease list? That would certainly narrow down the search. – itsme86 Jul 09 '18 at 23:07
  • You could use the Parallel.Foreach from Task Parallel Library to speed up the parallel query. (spawning so many threads with "new Thread" is no real performance increase) – Tintenfiisch Jul 09 '18 at 23:08
  • @itsme86 My goal is to make this process automatic. Although I could end up doing that, I don't think it's so hard to achieve this. But I'll consider – Joaquin Guevara Jul 09 '18 at 23:10
  • @Tintenfiisch I'll try that out. Thank you – Joaquin Guevara Jul 09 '18 at 23:11
  • IMHO, need clarification on _"I want to find another instance of my program in order to sync their contents"_ and _maybe_ a different approach can be considered. – EdSF Jul 09 '18 at 23:47

1 Answers1

6

ICMP and ARP are for locating devices, not services. That's what UDP Broadcast was designed for.

Add a UDP listener to your program using UdpClient on some port that you select. To find instances of your program on the subnet, send a packet to the broadcast address. All machines on the subnet will get the packet, any that are running your program will return a packet to the originator with whatever information you need to know about them. It could be a simple query/acknowledge type exchange or a rich set of information.

The beauty of this is that you send one packet, get some responses, and the whole thing is over in a matter of milliseconds... and it's the same speed on a /16 network as it is on a /24... or a /8 for that matter.

Check out this post for a simple code sample of how to do UDP broadcast.

Corey
  • 15,524
  • 2
  • 35
  • 68
  • I would add that if there are wireless clients, it's possible one broadcast may not be enough. – Kyle Huff Jul 09 '18 at 23:59
  • This is it. You nailed it. Thank you very much! – Joaquin Guevara Jul 10 '18 at 00:08
  • Now that I wonder, do Ethernet connected devices also respond to this UDP Broadcast? – Joaquin Guevara Jul 10 '18 at 00:08
  • All devices on the same subnet should receive it, but it's not guaranteed since UDP doesn't do any error handling. As Kyle pointed out it's a good idea to do the whole thing multiple times to maximize the chance that you get to all the devices. – Corey Jul 10 '18 at 00:18
  • @Corey I'll add multiple calls to make sure. Although one of my 2 laptops is not receiving the UDP Broadcast, not even on Wireshark. May it be the Firewall? – Joaquin Guevara Jul 10 '18 at 02:04
  • Yes, Windows Firewall on the laptop is probably blocking the packets. – Corey Jul 10 '18 at 02:29