Правильный способ сканирования диапазона IP-адресов

Учитывая диапазон IP-адресов, введенных пользователем (различными способами), я хочу определить, на каком из этих компьютеров работает программное обеспечение, с которым я могу общаться.

Вот основной процесс:

  1. Пингуйте эти адреса, чтобы найти доступные машины

  2. Подключитесь к известной розетке на доступных машинах

  3. Отправить сообщение на успешно установленные сокеты

  4. Сравните ответ с ожидаемым ответом

Шаги 2-4 являются прямыми для меня. Каков наилучший способ реализовать первый шаг в.NET?

Я смотрю на класс System.Net.NetworkInformation.Ping. Должен ли я пинговать несколько адресов одновременно, чтобы ускорить процесс? Если я пингую один адрес за раз с большим таймаутом, это может занять вечность. Но с небольшим таймаутом я могу пропустить некоторые машины, которые доступны.

Иногда кажется, что пинг не работает, даже когда я знаю, что адрес указывает на активный компьютер. Нужно ли дважды пинговать в случае отклонения запроса?

В довершение всего, когда я сканирую большие коллекции адресов с отключенным сетевым кабелем, Ping генерирует исключение NullReferenceException в FreeUnmanagedResources().!?

Любые указатели на лучший подход к сканированию ряда IP-адресов, как это?

4 ответа

Решение

Поскольку не все машины отвечают на эхо-запросы (в зависимости от настроек брандмауэра), я предлагаю пропустить шаг 1, если это возможно.

Если вы знаете машины, к которым вы будете подключаться для ответа на эхо-запросы, класс ping работает достаточно хорошо. Он отправляет только 1 пакет, поэтому ping более одного раза в случае сброса. Кроме того, по моему опыту, класс ping будет часто генерировать исключение, а не возвращать объект PingReply, если хост недоступен.

Это моя предлагаемая реализация:

public bool
   Ping (string host, int attempts, int timeout)
   {
      System.Net.NetworkInformation.Ping  ping = 
                                       new System.Net.NetworkInformation.Ping ();

      System.Net.NetworkInformation.PingReply  pingReply;

      for (int i = 0; i < attempts; i++)
      {
         try
         {
            pingReply = ping.Send (host, timeout); 

            // If there is a successful ping then return true.
            if (pingReply != null &&
                pingReply.Status == System.Net.NetworkInformation.IPStatus.Success)
               return true;
         }
         catch
         {
            // 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.
         }
      }

      // Return false if we can't successfully ping the server after several attempts.
      return false;
   }

Не забывайте головную боль людей, которые отрицают пинг в своих правилах брандмауэра.

Единственное, что я могу предложить, - это вопрос: нужно ли делать №1?

Разве вы не можете просто попытаться подключиться к этому известному сокету? Успешное соединение с этим сокетом убивает двух зайцев одним выстрелом: да, хост там / жив, и да, известный сокет открыт.

Этот тип ситуации хорошо подходит для многопоточности, запускает его в другом потоке и ждет, пока он вернется с ответом...

Поскольку многие люди упоминали, что Ping - не лучший способ определить, работает ли машина, если она абсолютно необходима для обнаружения всех доступных компьютеров в подсети, вы можете использовать некоторые из приемов, используемых сканером nmap для обнаружения доступных компьютеров.

Вы могли бы использовать nmap -sP 192.168.2.1-200 сканировать с 192.168.2.0 до 192.168.2.255

Звучит подозрительно, как будто кто-то пытается написать ботнет и сканирует подсети на наличие зараженных компьютеров.

Вряд ли когда-либо есть причина "обнаруживать компьютеры в сети", пусть они вместо этого говорят с вами, когда и если захотят.

Другие вопросы по тегам