Правильный способ сканирования диапазона IP-адресов
Учитывая диапазон IP-адресов, введенных пользователем (различными способами), я хочу определить, на каком из этих компьютеров работает программное обеспечение, с которым я могу общаться.
Вот основной процесс:
Пингуйте эти адреса, чтобы найти доступные машины
Подключитесь к известной розетке на доступных машинах
Отправить сообщение на успешно установленные сокеты
Сравните ответ с ожидаемым ответом
Шаги 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
Звучит подозрительно, как будто кто-то пытается написать ботнет и сканирует подсети на наличие зараженных компьютеров.
Вряд ли когда-либо есть причина "обнаруживать компьютеры в сети", пусть они вместо этого говорят с вами, когда и если захотят.