|
|
|
новичок
      
участник
Last Login: 14.03.2007 1:06
Сообщ.: 8,
Visits: 46
|
|
Доброго времени суток!
Существует задача
Получить список всех локальных FTP-серверов, находящихся в онлайне. Это значит, что есть диапазон IP-адресов 192.168.*.*, каждый из которых необходимо проверить на наличие на нём ftp-сервера (TCP, 21 порт).
Как я решал эту проблему
1. Пробую "влоб" пытаться подключиться к серверам через System.Net.Sockets.TcpClient. Данный вариант не устраивает по двум причинам: необходимо сильно уменьшить время ожидания подключения, т.к. стандартное значение таймаута слишком велико для столь немаленького диапазона хостов. Как менять таймаут подключения (это ни SendTimeout, ни ReceiveTimeout) я не нашёл. Ситуация ещё ухудшается тем, что в случае невозможности подключения вылетает исключение, а его отлов это снова большие потери во времени и уже поэтому не лучший вариант.
2. Да, можно использовать асинхронную операцию BeginConnect, но она не устроивает по тем причинам, что один сокет нельзя одновременно использовать для нескольких подключений (кто бы сомневался), а создание большого числа сокетов тоже нежелательно, в итоге это может кончиться сотнями открытых портов, всяческими переполнениями, т.к. насколько я знаю, на их количество в системе тоже есть ограничение.
3. Хорошо, таймаут можно настроить у фунции System.Net.NetworkInformation.Ping.Send, а потом в случае положительного результата можно уже пробовать подключаться по 21 порту. Но: на компьютере с доступным FTP сервером никто не запрещает заблокировать приём или ответ на ICMP echo message - т.е. часть адресов мы потеряем.
Вопрос остаётся - как с минимальными потерями во времени получить полный список активных FTP в локальной сети?
|
|
|
|
|
Supreme Being
модератор
Last Login: 04.05.2008 13:32
Сообщ.: 7 240,
Visits: 65 445
|
|
| Я бы пробовал комбинировать п.1 и 2. В любом случае придется перебирать все адреса, по другому никак.
|
|
|
|
|
новичок
      
участник
Last Login: 14.03.2007 1:06
Сообщ.: 8,
Visits: 46
|
|
Ура. Ни на gotdotnet, ни на realcoding ответа так и не дождался. :)
1. Весь диапазон адресов обрабатывать придётся - это не вызывает сложностей или каких-либо проблем. Кроме одной... Если над каждым неработающим адресом мы будем работать хотя бы даже по паре секунд, то опрос всей сети займёт огромное время.
2. Описанный мной второй вариант всецело основан на первом (всё та же попытка подключиться через сокет), только с асинхронной структурой. Как уже написал, и у него есть куча недостатков.
Поэтому по сути вопрос можно свести к задаче об изменении значения таймаута ожидания ответа на запрос подключения. Подключаться можно абсолютно любым способом.
|
|
|
|
|
Supreme Being
модератор
Last Login: 04.05.2008 13:32
Сообщ.: 7 240,
Visits: 65 445
|
|
Конечно это займет много времени. Шутка ли проверить 65 тысяч машин адресов. Пара секунд на одну проверку это даже мало. Не факт что каждый сервер успеет ответить в течение такого короткого интервала.Механизм исключений замедляет поиск, все верно, но в среде .NET нет классов не использующих исключения. Можно начать использовать функции WinAPI из Windows Sockets 2 там исключений точно нет. Как изменить таймаут соединения в .NET я не знаю. Так как тебе надо опросить много адресов, то в любом случае придется выполнять парралельную обработку: через асинхронные соединения или многопоточность. Или и то и другое. Конечно в системе существует ограничение на одновременное кол-во открытых сокетов и здесь придется эксперментировать в поиске баланса между скоростью работы и использованием ресурсов машины. Извини, что не могу дать более полный ответ подкрепленный кодом. Я не специалист в работе с сокетами.
|
|
|
|
|
новичок
      
участник
Last Login: 14.03.2007 1:06
Сообщ.: 8,
Visits: 46
|
|
Насчёт пары секунд - врятли это мало, это очень много. В 90% случаев при нормально работающей хоть даже 10-мбитной локальной сети действительно работающий сервер сразу отвечает менее, чем за 100-200 миллисекунд, на такие ответы и надо рассчитывать в идеале.
Мне, честно говоря, не понятно, почему Ping имеет таймаут, а Connect в сокетах - нет...
|
|
|
|
|
Supreme Being
модератор
Last Login: 04.05.2008 13:32
Сообщ.: 7 240,
Visits: 65 445
|
|
| Ответ в течение 100-200 миллисекунд возможен в случае незагруженной сети и низкой нагрузки на сам ftp сервер. В реальной ситуации это не обязательно будет выполняться. Я бы не стал рассчитывать на ответ в течение такого короткого интервала.
|
|
|
|
|
новичок
      
участник
Last Login: 14.03.2007 1:06
Сообщ.: 8,
Visits: 46
|
|
| Да, вполне возможно, это так. Но боюсь, что, не зная, как его значение поменять, рассуждать об этом преждевременно...
|
|
|
|
|
Supreme Being
      
участник
Last Login: 23.04.2007 23:36
Сообщ.: 1 541,
Visits: 16 997
|
|
| Я бы делал так: 1. Запускал бы для каждого адреса отдельный поток, который репортил бы о результате через общее для них событие. Причем обработчик события должен быть помечен как синхронизированный либо использовать локи/семафоры. 2. Таймаутом на TCP-соединениях рулить не получится даже в WinAPI. Ну, не поддерживают блокирующие сокеты таймаута... Поэтому нужно юзать неблокирующий сокет (SetSocketOption()). И самостоятельно ждать нужный таймаут.
|
|
|
|
|
новичок
      
участник
Last Login: 14.03.2007 1:06
Сообщ.: 8,
Visits: 46
|
|
| Спасиба, попробую так и делать.
|
|
| |