Пинг всех девайсов в локальной сети, варианты?

Сеть в Unity3D

Пинг всех девайсов в локальной сети, варианты?

Сообщение IDoNotExist 04 фев 2019, 10:50

В общем цель - получить IP адреса всех девайсов и их имена в домашней локальной сети.
Путём быстрого гугления попробовал вариант пинга через System.Net.NetworkInformation.Ping:
Синтаксис:
Используется csharp
using NetPing = System.Net.NetworkInformation.Ping;

                public IEnumerator ScanVar2()
                {
                        string subnet = "192.168.0.";

                        for (int i = 1; i < 255; i++)
                        {
                                string sAddress = subnet + i.ToString();
                                Debug.Log(sAddress);

                                try
                                {
                                        IPAddress addr = IPAddress.Parse(sAddress);

                                        NetPing ping = new NetPing();
                                        PingReply reply = ping.Send(addr, 900);

                                        if (reply.Status != IPStatus.Success)
                                                continue;

                                        IPHostEntry host = Dns.GetHostEntry(addr);
                                        Debug.Log("HOST: " + sAddress + "; " + host.HostName);
                                }
                                catch (System.Exception ex) { Debug.LogException(ex); }

                                yield return null;
                        }
                }
 


В результате получаю ошибку:
ArgumentException: The IPEndPoint was created using InterNetworkV6 AddressFamily but SocketAddress contains InterNetwork instead, please use the same type.
System.Net.IPEndPoint.Create (System.Net.SocketAddress socketAddress)


Какого фига он пытается создать сокет с IP6 адресом, когда я явно задаю ему ip4 адрес мне категорически не понятно, как это победить в гугле не нашел.

Ладно, вроде бы фигня вопрос, обнаружил что в Unity имеется свой класс Ping.
Попробовал:
Синтаксис:
Используется csharp
               
                //======================================================================================
                public IEnumerator ScanVar1()
                {
                        string subnet =  "192.168.0.";

                        for (int i = 1; i < 255; i++)
                        {
                                string sAddress = subnet + i.ToString();
                                Debug.Log(sAddress);

                                yield return TryPing(sAddress, 2000, delegate(UnityEngine.Ping ping)
                                {
                                        try
                                        {
                                                Debug.LogError(ping.time);
                                                IPAddress addr = IPAddress.Parse(sAddress);
                                                IPHostEntry host = Dns.GetHostEntry(addr);
                                                Debug.Log("HOST: " + sAddress + "; " + host.HostName);
                                        }
                                        catch (System.Exception ex) { Debug.LogException(ex); }

                                });

                                yield return null;
                        }
                }

                //======================================================================================
                private IEnumerator TryPing(string sAddr, int timeout, System.Action<UnityEngine.Ping> onDone)
                {
                        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                        sw.Start();

                        UnityEngine.Ping ping = new UnityEngine.Ping(sAddr);

                        while (!ping.isDone)
                        {
                                if (sw.ElapsedMilliseconds > timeout)
                                        break;

                                yield return null;
                        }

                        if (ping.isDone)
                                onDone(ping);
                }
 


Пинг идёт, результат возвращается НО! Только со всех ПК в сети, мобилки не пингуются, подозреваю что в них по дефолту заблочено нечто связанное с ICMP протоколом. Плюс, через Dns.GetHostEntry(addr), возвращается некорректное сетевое имя (представляет из себя IP а не имя ПК). Как всё это победить, знает кто?
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1289
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение seaman 04 фев 2019, 19:08

1. Что за NetPing? Может Ping?
2. У меня другая ошибка с Ping, которая связана с уровнем доступа. При запуске от админа - ошибок нет.
3. Посмотри это может поможет.
4. Имя хоста получить не удалось :(

Да, мобилки пингуются.
seaman
Адепт
 
Сообщения: 7573
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение IDoNotExist 04 фев 2019, 22:06

seaman писал(а):1. Что за NetPing? Может Ping?

using NetPing = System.Net.NetworkInformation.Ping;

seaman писал(а):2. У меня другая ошибка с Ping, которая связана с уровнем доступа. При запуске от админа - ошибок нет.
3. Посмотри это может поможет.

В общем то проблему в эксепшеном решил путём отключения ip6 протокола в свойствах сетевого адаптера, но один фиг мобилки не пингуются, пошел другим путём, а именно:
Скачал приложение которое это умеет, и посмотрел через Wireshark какие пакеты приходят на ПК, в общем то ICMP не приходят, а приходят ARP и NBNS, получается смысл почти тот же самый, вместо пинга - ARP, а вместо Dns.GetHostEntry - NBNS. Проблема в том, что в .NET насколько я понял, из быстрого гугления, не так просто отправить пакеты этих протоколов, либо с помощью дополнительных библиотек, либо с помощью костылей, буду гуглить дальше.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1289
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение Woolf 04 фев 2019, 22:13

но один фиг мобилки не пингуются

Только хотел сказать, что ICMP на мобилках и не будет работать, но вы уже сами разобрались.
Разработчик Atom Fishing - Рыбалка на поплавок, донку, нахлыст, блесну в постъядерный период.
Разработчик Atom Fishing II - Первая 3D MMO про рыбалку
Аватара пользователя
Woolf
Адепт
 
Сообщения: 6613
Зарегистрирован: 02 мар 2009, 16:59

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение seaman 04 фев 2019, 23:01

ICMP на мобилках и не будет работать

Не знаю что там будет, не будет работать, но мой андроид спокойно по wifi пингуется. И встроенным пингом из командной строки и Ping .NET
Скрипт:
https://pastebin.com/zYHi21kd
Запускать Юнити надо "от другого пользователя" - Администратор
seaman
Адепт
 
Сообщения: 7573
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение IDoNotExist 05 фев 2019, 09:15

seaman писал(а):Не знаю что там будет, не будет работать, но мой андроид спокойно по wifi пингуется. И встроенным пингом из командной строки и Ping .NET
Скрипт:
https://pastebin.com/zYHi21kd

Во, та мобилка на которую установил Fing, начала пинговаться, но другая, на которой его нет один фиг не пингуется, обе мобилки Xiaomi, да в общем то ICMP не самый удачный вариант, если его отключить в винде на ПК, то он уже не пингуется, но Fing его всё-равно находит.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1289
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение IDoNotExist 13 фев 2019, 16:58

Получилось реализовать NBNS запросы, взял за основу это http://humpreyonsecurity.blogspot.com/2011/08/using-c-and-netbios-ns-to-get.html, привёл в относительный порядок, получилось это:
Синтаксис:
Используется csharp

        public static class NBNSNameFlags
        {
                public const byte GROUP_NAME0 = 0;
                public const byte GROUP_NAME1 = 30;

                public const byte USER_NAME = 3;
                public const byte DEVICE_NAME = 32;
        }

        public struct NBNSData
        {
                public string IP { get; set; }
                public string MacAddress { get; set; }
                public Dictionary<byte, string> NamesTable { get; set; }

                public System.Exception Exception { get; set; }

                public bool IsNull
                {
                        get { return NamesTable == null || NamesTable.Count == 0; }
                }

                public string DeviceName
                {
                        get { return GetName(NBNSNameFlags.DEVICE_NAME); }
                }

                public string WorkGroup
                {
                        get
                        {
                                string sRes = GetName(NBNSNameFlags.GROUP_NAME0);
                                if (!string.IsNullOrEmpty(sRes))
                                        return sRes;

                                return GetName(NBNSNameFlags.GROUP_NAME1);
                        }
                }

                public string UserName
                {
                        get { return GetName(NBNSNameFlags.USER_NAME); }
                }

                public string GetName(byte flag)
                {
                        if (NamesTable == null)
                                return "";

                        string sRes;
                        if (!NamesTable.TryGetValue(flag, out sRes))
                                return "";

                        return sRes;
                }

                public string ToStringSmart()
                {
                        StringBuilder sb = new StringBuilder();

                        sb.AppendLine(string.Format("IP: {0}; ", IP));

                        if (Exception == null)
                        {
                                sb.AppendLine(string.Format("MAC: {0}; ", MacAddress));
                                sb.AppendLine(string.Format("DEVICE: {0}; ", DeviceName));
                                sb.AppendLine(string.Format("GROUP: {0}; ", WorkGroup));
                        }
                        else
                        {
                                sb.AppendLine(Exception.Message);
                        }

                        return sb.ToString();
                }
        }

        public class NBNS
        {
                public static readonly byte[] QUERY_DATA = new byte[50]
                {
                                0x82, 0x28, 0x00, 0x00, 0x00,
                                0x01, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x20, 0x43, 0x4B,
                                0x41, 0x41, 0x41, 0x41, 0x41,
                                0x41, 0x41, 0x41, 0x41, 0x41,
                                0x41, 0x41, 0x41, 0x41, 0x41,
                                0x41, 0x41, 0x41, 0x41, 0x41,
                                0x41, 0x41, 0x41, 0x41, 0x41,
                                0x41, 0x41, 0x41, 0x41, 0x41,
                                0x00, 0x00, 0x21, 0x00, 0x01
                };

                //Recieves an IP address and any available port to listen on
                public static bool SendNBNSPacket(IPAddress addr, int intPortNum, out NBNSData nbnsData)
                {
                        nbnsData.IP = addr.ToString();
                        nbnsData.Exception = null;

                        //Declare MAC Address
                        string strMAC = "";
                        Dictionary<byte, string> namesTable = null;

                        bool bResponce = false;

                        //Datagram declaration expected to receive from host
                        byte[] dataIn = new byte[4096];

                        using (Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
                        {
                                System.Net.IPEndPoint ipEndPT = new System.Net.IPEndPoint(addr, 137);
                                //System.Net.EndPoint endPT = (System.Net.EndPoint)ipEndPT;

                                System.Net.IPEndPoint inIPEndPT = new System.Net.IPEndPoint(addr, intPortNum);
                                System.Net.EndPoint inEndPT = (System.Net.EndPoint)inIPEndPT;

                                soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 50);
                                soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 50);

                                int intTries = 0;


                                do
                                {
                                        soc.SendTo(QUERY_DATA, ipEndPT);

                                        try
                                        {
                                                //Get data from host
                                                soc.ReceiveFrom(dataIn, ref inEndPT);
                                                bResponce = true;
                                        }
                                        catch (System.Exception ex)
                                        {
                                                intTries++;
                                                nbnsData.Exception = ex;
                                        }
                                }
                                while ((!bResponce) && intTries < 1);
                        }

                        if (bResponce)
                        {
                                //parse the MAC Address from the data received from host
                                strMAC = GetMAC(dataIn);
                                namesTable = GetRemoteMachineNameTable(dataIn);
                        }
                        else
                        {
                                strMAC = "Host Unreachable";
                        }

                        nbnsData.MacAddress = strMAC;
                        nbnsData.NamesTable = namesTable;

                        return bResponce;
                }

                private static Dictionary<byte, string> GetRemoteMachineNameTable(byte[] dtResponse)
                {
                        Int32 iNamesLng = 0;
                        Dictionary<byte, string> resMap = new Dictionary<byte, string>();

                        //Get no of names in the Response Packet (position 56 of response Packet)
                        iNamesLng = Convert.ToInt32(dtResponse[56]);

                        for (int i = 0; i <= iNamesLng - 1; i++)
                        {
                                string CurrentName = "";
                                //Get first 15 characters after position 56
                                for (int x = 1; x <= 15; x++)
                                {
                                        //18 characters per name,
                                        byte newByte = dtResponse[x + (56 + i * 18)];

                                        //checked if printable chars 0x21 to 0x7E
                                        //0x20 = space
                                        //0x7F = Delete
                                        //TRAP GROUP NAMES - Must have a 1E NetBios Suffix
                                        if (newByte > 0x19 && newByte < 0x7E)
                                                CurrentName += Convert.ToChar(newByte);
                                        else
                                                CurrentName += " ";
                                }

                                //HEC Notes
                                //NAME_FLAGS = Bytes 17 and 18 Definition
                                //Taken from http://www.faqs.org/rfcs/rfc1002.html

                                byte flag = dtResponse[16 + (56 + i * 18)];
                                resMap[flag] = CurrentName;

                                /*RemoteMachineNames.Add(CurrentName +
                                        String.Format("{0:X2}", dtResponse[16 + (56 + remoteNameCounter * 18)])
                                                + Convert.ToString(dtResponse[17 + (56 + remoteNameCounter * 18)], 2)
                                                .PadLeft(8, '0'));*/

                        }

                        return resMap;
                }

                private static string GetMAC(byte[] dtResponse)
                {
                        string strMac = "";
                        //intStart reads the value @ byte 56 which contains the
                        //no of names in the Response Packet
                        int intStart = (int)dtResponse[56];

                        //1 name contains 16 bytes followed by 2 bytes name flag = 18 Bytes
                        int intOffset = 56 + intStart * 18 + 1;

                        for (int x = 0; x < 6; x++)
                        {
                                strMac += String.Format("{0:X2}", dtResponse[intOffset + x]) + ":";
                        }

                        strMac = strMac.Remove(strMac.Length - 1, 1);
                        return strMac;
                }

        }
 

Теперь могу получать с ПК на Windows, корректное имя, мак адрес, рабочую группу и т.д., как получить то же самое с Андроид и Мак девайсов, еще разбираюсь...
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1289
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение Cr0c 13 фев 2019, 17:07

IDoNotExist писал(а):Теперь могу получать с ПК на Windows, корректное имя, мак адрес, рабочую группу и т.д., как получить то же самое с Андроид и Мак девайсов, еще разбираюсь...

служба имён NetBIOS
действительно странно, что в мобилках этого нет (сарказм)
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 2904
Зарегистрирован: 19 июн 2015, 13:50

Re: Пинг всех девайсов в локальной сети, варианты?

Сообщение IDoNotExist 13 фев 2019, 17:46

Cr0c писал(а):
служба имён NetBIOS
действительно странно, что в мобилках этого нет (сарказм)

Не понял если честно к чему тут ваш сарказм, про NetBIOS я в курсе, умею в гугл и в википедию. По существу комментарии будут? Какие запросы и для какого протокола нужны для Андроида и Мака?
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1289
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist


Вернуться в Сеть

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4