发现局域网上的所有设备

时间:2019-01-03 22:12:03

标签: c# xamarin.forms

在我的Xamarin Forms应用程序中,我试图发现我连接到的本地网络上的所有设备。我的方法是首先获取设备IP地址,并使用前3个数字来了解网关是什么(第一个数字始终为192)。然后,ping该网关上的每个地址。这是我的代码:

public partial class MainPage : ContentPage
{
    private List<Device> discoveredDevices = new List<Device>();

    public MainPage()
    {
        InitializeComponent();

        Ping_all();
    }

    private string GetCurrentIp()
    {
        IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
        string ipAddress = string.Empty;
        if (addresses != null && addresses[0] != null)
        {
            ipAddress = addresses[0].ToString();
        }
        else
        {
            ipAddress = null;
        }

        return ipAddress;
    }

    public void Ping_all()
    {
        string ip = GetCurrentIp();

        if (ip != null)
        {
            //Extracting and pinging all other ip's.
            string[] array = ip.Split('.');
            string gateway = array[0] + "." + array[1] + "." + array[2];

            for (int i = 2; i <= 255; i++)
            {
                string ping_var = $"{gateway}.{i}";

                //time in milliseconds           
                Ping(ping_var, 4, 4000);
            }
        }
    }

    public void Ping(string host, int attempts, int timeout)
    {
        for (int i = 0; i < attempts; i++)
        {
            new Thread(delegate ()
            {
                try
                {
                    System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
                    ping.PingCompleted += new PingCompletedEventHandler(PingCompleted);
                    ping.SendAsync(host, timeout, host);
                    // PingCompleted never gets called
                }
                catch(Exception e)
                {
                    // Do nothing and let it try again until the attempts are exausted.
                    // Exceptions are thrown for normal ping failurs like address lookup
                    // failed.  For this reason we are supressing errors.
                }
            }).Start();
        }
    }

    private void PingCompleted(object sender, PingCompletedEventArgs e)
    {
        string ip = (string)e.UserState;
        if (e.Reply != null && e.Reply.Status == IPStatus.Success)
        {
            string hostname = GetHostName(ip);
            string macaddres = GetMacAddress(ip);

            var device = new Device()
            {
                Hostname = hostname,
                IpAddress = ip,
                MacAddress = macaddres
            };

            discoveredDevices.Add(device);
        }
    }

    public string GetHostName(string ipAddress)
    {
        try
        {
            IPHostEntry entry = Dns.GetHostEntry(ipAddress);
            if (entry != null)
            {
                return entry.HostName;
            }
        }
        catch (SocketException)
        {

        }

        return null;
    }

    public string GetMacAddress(string ipAddress)
    {
        string macAddress = string.Empty;
        System.Diagnostics.Process Process = new System.Diagnostics.Process();
        Process.StartInfo.FileName = "arp";
        Process.StartInfo.Arguments = "-a " + ipAddress;
        Process.StartInfo.UseShellExecute = false;
        Process.StartInfo.RedirectStandardOutput = true;
        Process.StartInfo.CreateNoWindow = true;
        Process.Start();
        string strOutput = Process.StandardOutput.ReadToEnd();
        string[] substrings = strOutput.Split('-');
        if (substrings.Length >= 8)
        {
            macAddress = substrings[3].Substring(Math.Max(0, substrings[3].Length - 2))
                     + "-" + substrings[4] + "-" + substrings[5] + "-" + substrings[6]
                     + "-" + substrings[7] + "-"
                     + substrings[8].Substring(0, 2);
            return macAddress;
        }
        else
        {
            return "OWN Machine";
        }
    }
}

我进入尝试ping的部分:

System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
ping.PingCompleted += new PingCompletedEventHandler(PingCompleted);
ping.SendAsync(host, timeout, host);

但是PingCompleted从未被调用。也不抛出异常。知道为什么吗?我正在物理Android设备上运行它。

编辑

PingCompleted现在开始受到我的呼唤,不确定为什么以前不起作用。但由于它找不到资源,它现在在GetMacAddress行的Process.Start();函数中崩溃。

1 个答案:

答案 0 :(得分:0)

我最终使用了这个非常强大且易于使用的库:

https://github.com/Yortw/RSSDP

它实际上并没有找到网络上的所有设备,而是使用SSDP(简单搜索发现协议)来快速查找正在网络上使用此协议广播服务的所有设备。我将其过滤为仅扫描运行我的应用程序的设备,而这正是我真正需要的。只需一秒钟即可发现我的设备,这比对255个地址执行ping操作要快得多。

在文档中,您将看到:

var deviceDefinition = new SsdpRootDevice()
{
    CacheLifetime = TimeSpan.FromMinutes(30), //How long SSDP clients can cache this info.
    Location = new Uri("http://mydevice/descriptiondocument.xml"), // Must point to the URL that serves your devices UPnP description document. 
    DeviceTypeNamespace = "my-namespace",
    DeviceType = "MyCustomDevice",
    FriendlyName = "Custom Device 1",
    Manufacturer = "Me",
    ModelName = "MyCustomDevice",
    Uuid = GetPersistentUuid() // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
};

对于Location,我将其设置为设备的IP。这样发现它的另一台设备也可以拥有IP。我不认为应该以这种方式使用它,但是它对我有用,我不知道为什么不这样做。

我在2个物理Android设备上进行了测试。