Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2012.03.11;
Скачать: [xml.tar.bz2];

Вниз

Проблема с потоками сканирования   Найти похожие ветки 

 
bvv   (2009-09-17 14:57) [0]

Знатоки!
Написал программу сканирования сети.
Для сокращения времени сканирования разбил проверку адресов IP на потоки, если результаты поиска по каждому потоку выводить в свой файл проблем никаких. Если результаты поиска записывать во временный массив простая синхронизации потоков работает только при небольшом количестве потоков. Критические секции немного улучшают ситуацию, но поиск в 256 потоков находит число IP-адресов гораздо больше чем с 1792 потока, переход на Mutex проблемы не решает и оптимальным числом потоков остаётся ~512. Mutex используется только при завершении работы потока для записи результатов поиска в общий массив, да и то, для каждого потока организован свой раздел в массиве, в который нет доступа другим потокам. Процессор двух ядерный.
Всё процессорное время, во время сканирования, съедают Svchost и Acs.
Почему происходят такое различие результатов поиска, если число потоков отличается в три раза, если верить теории этого быть не должно.

С благодарностью Вл.


 
Сергей М. ©   (2009-09-17 15:13) [1]

И куда столько потоков ?
Очуметь же можно - аж под две тысячи)
Хотя для решения задачи с неменьшей эффективностью вполне хватит и дюжины)


 
bvv   (2009-09-17 15:45) [2]

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


 
Сергей М. ©   (2009-09-17 16:41) [3]


> время тратится на ожидание ответа


Ну так ведь поток, получивший ответ, можно тут же напрячь пинговать следующий адрес..

А пинг-то какими средствами ? raw sockets или wininet-интерфейс ?


 
bvv   (2009-09-17 16:44) [4]

Так ведь я так и делаю, каждый поток пингует свой диапазон адресов.


 
Anatoly Podgoretsky ©   (2009-09-17 16:52) [5]

> bvv  (17.09.2009 16:44:04)  [4]

Не очень верно, пусть поток сканирует только один адрес, тогда быстрее будет. 256 потоков достаточно, для блока С, а к нему можно привести и В и С.
По сути получается почти равное время, что для одного потока.


 
bvv   (2009-09-17 17:03) [6]

Для С сети проблем вообще никаких нет, если В сетку сканировать как последовательный ряд С сетей, судя по всему Вы правы, но тогда каждый раз нужно создавать и гасить новые потоки, а это время. Гораздо проще, весь диапазон разбить на равные отрезки, и на каждый отрезок создать свай поток, это ничему не противоречит, поскольку в каждом потоке не проверяется больше одной станции, и мы не выходим за предельное число потеков в одном процессе, кроме того, если каждый поток записывает результаты поиска в свой файл, тогда здесь даже синхронизация потоков не нужна, всё на Ура проходит.


 
Сергей М. ©   (2009-09-17 17:04) [7]


> каждый поток пингует свой диапазон адресов


А пинговать он должен один адрес, который ему выдаст диспетчер.
Т.е. поток получил адрес, выполнил пинг, отчитался диспетчеру о результатах пинга и ждет получения след.адреса.


 
bvv   (2009-09-17 17:12) [8]

Естественно один, цикл выбирает по одному адресу, и пока не получен ответ на адрес, следующий пинг не начнётся, тоже и с Файлами, но там я для записи результата открывал файл,  записывал и закрывал. с массивом этого делать не нужно а это выигрыш по времени.


 
Сергей М. ©   (2009-09-17 17:24) [9]

На вопрос в [3] ответишь ?


 
bvv   (2009-09-17 17:34) [10]

Сергей, я не не знаю что значит [3] т.к. на форум пришёл впервые, да если честно то и потоками занимаюсь недавно, прочитал и решил модернизировать свою программу, и тут же фэйсом об тэйбол.


 
Сергей М. ©   (2009-09-17 19:34) [11]

При чем здесь потоки ?
Я о пинге, а не о потоках ..


 
bvv   (2009-09-18 08:38) [12]

Сергей, извините, вчере пришлось срочно убегать.
Поиск станци в сети выполняется функцией IPAddrToName
В старой программе для поиска невидимых станций исполь зовался ещё и сокет, но это к делу не относится.


 
Сергей М. ©   (2009-09-18 08:48) [13]


> Поиск станци в сети выполняется функцией IPAddrToName


Что за ерунда ?
Даже по названию ф-ции следует, что она предназначена совсем для иной задачи.
И откуда она у тебя взялась ?
Сдул неглядя из
http://www.google.ru/search?q=IPAddrToName&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ru:official&client=firefox
?)


> для поиска невидимых станций исполь зовался ещё и сокет


Каких таких "невидимых" ?
И куда делся сокет в "новой программе" ?)


> это к делу не относится


Это к делу относится самым прямым образом.


 
bvv   (2009-09-18 09:30) [14]

Сдул конечно, любая вещь гдде нибудь сдувается дорабатывается и снова сдувается.
Перебирая в цикле адреса определяю наличие станций если есть имя значит есть станция.
Любая проверка наличия станции в сети, так или иначе связана с установкой связи с ней, (если конечно не берётся готовая таблица станций) связь осуществляется соединением по порту, на некоторых станциях может быть запрещён отклик на запрос IPAddrToName, но если станция в сети, значит у неё должен быть открыт как минимум один порт. С помощью сокета можно это зделать, и делалось, но сейчас главной задачей было разобраться с работой потоков, и поиск другиз станций меня пока не интересует. Но в принципе я могу решить задачу сканирования станции обойдясь без всякой синхронизации потоков, просто записывая результаты проверки во временные файлы а после тойже программой считывать сних информацию и обрабатывать её. Это даже решит другую проблему передачи информации из одного процесса в другой без всяких симафоров и Мьютексов, но хотелось разобраться с синхронизацией. Вопрос чисто теоретический, греть процессор никому ненужными синусами для рассмотрения этой проблемы - себя не уважать, вот и занимаюсь извращенияви в сети, а заодно и частично восполню пробел в знаниях.


 
Сергей М. ©   (2009-09-18 09:46) [15]


> если есть имя значит есть станция


Вот уж глупости.
Наличие зарегистрированного в обратной зоне DNS имени хоста ниак не связано с активностью и/или доступностью этого хоста.


> связь осуществляется соединением по порту


Хост не обязан отвечать на запросы на соединение по интересующему тебя порту, равно как и на ping-пакеты, и это ничуть не мешает ему присутствовать в сети.


> на некоторых станциях может быть запрещён отклик на запрос
> IPAddrToName


Эта ф-ция не обращается к "станциям", у нее иное назначение, см.выше (DNS)


> если станция в сети, значит у неё должен быть открыт как
> минимум один порт


С какого это перепугу "должен быть" ?
Это зависит от того как станция сконфигурирована, так что она вовсе не обязана быть чем-то должна твоему сканеру.

Ты пойми главное - не существует и не может существовать ни одного алгоритма, позволяющего со 100%-ной достоверностью определить факт присутствия узла в сети.


 
Сергей М. ©   (2009-09-18 09:49) [16]

Обнаружить в сети хост можно только если этого захочет администратор хоста.
Ну или по недосмотру или раздолбайству этого администратора)


 
Сергей М. ©   (2009-09-18 09:59) [17]


> Сдул конечно


Ну так надо было вникнуть в то что сдул, а не слепо верить в волшебные возможности сдутого)


 
bvv   (2009-09-18 10:02) [18]


> Ты пойми главное - не существует и не может существовать
> ни одного алгоритма, позволяющего со 100%-ной достоверностью
> определить факт присутствия узла в сети.

Так я с этим и не спорю, 100% гарантия может быть только по свершившемуся факту, (Машина врералась в дерево) это может не говорить о причинах свершившегося факта, но он либо есть либо нет.
Я не ставлю перед собой задачу 100% поиска станций, и не собираюсь заниматься их взломом, (Дорожу своим рабочим местом). Я говорю, это чисто теоретический вопрос с синхронизацией большого  числа потоков, поэтому данная функция IPAddrToName меня вполне устраивает, пусть прячутся и правильно делают, а то иногда встречаются станции с расшаренным С диском и даже Program Files нараспашку...
Иногда ставлю их в известность об этом, но чаще просто оставляю как есть, пусть сами разбираются, причём не только у нас но и за бугром такое бывает. Но это уже совсем другая тема...


 
Сергей М. ©   (2009-09-18 10:18) [19]


> функция IPAddrToName меня вполне устраивает


Приведи сюда ее код ..


> теоретический вопрос с синхронизацией большого  числа потоков


Теория при этом абсолютна та же самая, что и теория синхронизации малого числа потоков.
И если у тебя эта синхронизация не работает или работает не так как положено, значит у тебя ошибка в программе.


 
bvv   (2009-09-18 10:41) [20]

function IPAddrToName(IPAddr: string): string;
var
 S: String;
 SockAddrIn: TSockAddrIn;
 HostEnt: PHostEnt;
 WSAData: TWSAData;

 FSocket:TSocket; //Сокет.
 addr:TSockAddr; //Структура адреса.
begin
 S := "";
 WSAStartup($101, WSAData);
 SockAddrIn.sin_addr.s_addr := inet_addr(PChar(IPAddr));
 HostEnt := gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
 if HostEnt <> nil
  then
   begin
    S := StrPas(HostEnt^.h_name);
   end
 else
   begin
    if All
     then
      begin
       WSACleanup;
       addr.sin_family:=AF_INET; //Мутим адресацию, в нашем случае - асинхронная.
       addr.sin_addr.S_addr:=inet_addr(pchar(IPAddr));//Заполняем поле адреса.
       if WSAStartup($101,WSAData)<>0
        then
         begin
          //Если произошла ошибка при старте WinSock выводим сообщение и выходим.
          ShowMessage("ОШИБКА: при старте WinSock. " + IntToStr(GetLastError));
          exit;
         end;

         FSocket:=socket(AF_INET,SOCK_STREAM,0);//Создаем гнездо.
         if FSocket=INVALID_SOCKET
         then
          begin
           //Если если ошибка при создании гнезда то...
           ShowMessage("ОШИБКА: При создании сокета. " + IntToStr(GetLastError));
           exit;
          end;
          addr.sin_port:=htons(PortInvisible);//Присваеваем значению порта текущее значение счетчика.
          index := connect(FSocket,addr,sizeof(addr));
          if index = 0
          then
           begin
            //Ури, открытый порт.
            S := "Порт = " + IntToStr(PortInvisible);
           end;
          CloseSocket(FSocket);
      end; //if Form1.cbInVisible.Checked
    end;   //else
   Result := S;
 WSACleanup;
end;

procedure TThreadScanNet.Execute;
var
 i,k: Cardinal;
 s: string;
 SetM: WORD;
 ii: integer;
Label R;
begin
try
FreeOnTerminate := TRUE;
SetLength(Loc, 0);
with Form1 do
begin
 for k := iBegAddr to iEndAddr do
 begin
   s := IntToStr((k Shr 24) AND $FF) + "." +
        IntToStr((k Shr 16) AND $FF) + "." +
        IntToStr((k Shr 8) AND $FF) + "." +
        IntToStr(k AND $FF);

   s1 := IPAddrToName(s);
   if s1 <> ""
     then
      begin
       j := k;
       NumAdd := NumAdd + 1;
       SetLength(Loc, NumAdd);
       Loc[NumAdd-1].IP := j;
       Loc[NumAdd-1].Name := s1;

{
       SetM := WaitForSingleObject( Scan_Send.Form1.Mutex, INFINITE );
        if SetM = WAIT_OBJECT_0
          then Scan_Send.Form1.NumPc := Scan_Send.Form1.NumPc + 1;
       ReleaseMutex( Scan_Send.Form1.Mutex );
}

{
       EnterCriticalSection(Form1.StringSection); //Ждать освобождения Крит
       Scan_Send.ExZapisNetAddres[Num].NumAdd := Scan_Send.ExZapisNetAddres[Num].NumAdd + 1;
//        Synchronize(ChDate);
       LeaveCriticalSection(Form1.StringSection);
}

      end;
 end;  //for j := iBegAddr to iEndAddr do
end; //with Form1 do
finally
end;

// EnterCriticalSection(Form1.StringSection); //Ждать освобождения Крит

R:
SetM := WaitForSingleObject( Scan_Send.Form1.Mutex, INFINITE );
if SetM = WAIT_OBJECT_0
// if WaitForSingleObject( Scan_Send.Form1.Mutex, 2000 ) = WAIT_OBJECT_0
 then
  begin
   SetLength(Scan_Send.ExZapisNetAddres[Num].Lisp,NumAdd) ;
   Scan_Send.ExZapisNetAddres[Num].NumAdd := NumAdd;
   for ii := 0 to NumAdd - 1 do
    begin
     Scan_Send.ExZapisNetAddres[Num].Lisp[ii].AddNet := Loc[ii].IP;
     Scan_Send.ExZapisNetAddres[Num].Lisp[ii].AddName := Loc[ii].Name;
    end;
    Scan_Send.ExZapisNetAddres[Num].Nit := FALSE;
    Scan_send.NumEndThread := Scan_send.NumEndThread + 1;

    ReleaseMutex( Scan_Send.Form1.Mutex );

  end
 else
  begin
//    ReleaseMutex( Scan_Send.Form1.Mutex );
   Sleep(0);
   goto R;
  end;

//   ReleaseMutex( Scan_Send.Form1.Mutex );

{
 ReleaseMutex( Scan_Send.Form1.Mutex );

 sleep(500);
}
//  Scan_Send.ExZapisNetAddres[Num].ThreadScanNet := TRUE;
//  LeaveCriticalSection(Form1.StringSection); //Освободить Крит
end;


 
Сергей М. ©   (2009-09-18 10:57) [21]

Какой ужас ..

Мало того, что IPAddrToName занимается не тем чем ей положено согласно названию, да еще и бред какой-то:


> Мутим адресацию, в нашем случае - асинхронная


 
bvv   (2009-09-18 11:10) [22]

Я понимаю, но в данном случае эта часть кода не используется, хотя когда эта программа работала без динамического массива, а результат выводился в файл она нисколько не мешала, да и сейчас при работе отключается через  if All
Мешать она никак не может.


 
Сергей М. ©   (2009-09-18 11:16) [23]


> в данном случае эта часть кода не используется


Какая такая "часть кода" не используется ?
Зачем ты приводишь код, который не используется ?
Меня он абсолютно не интересует.
Приводи только актуальный код, без отсебячины и чьих-то бредовых комментарием про "муть".


 
bvv   (2009-09-18 11:21) [24]

function IPAddrToName(IPAddr: string): string;
var
 S: String;
 SockAddrIn: TSockAddrIn;
 HostEnt: PHostEnt;
 WSAData: TWSAData;

 FSocket:TSocket; //Сокет.
 addr:TSockAddr; //Структура адреса.
begin
 S := "";
 WSAStartup($101, WSAData);
 SockAddrIn.sin_addr.s_addr := inet_addr(PChar(IPAddr));
 HostEnt := gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
 if HostEnt <> nil
  then
   begin
    S := StrPas(HostEnt^.h_name);
   End;
   Result := S;
 WSACleanup;
end;


 
Сергей М. ©   (2009-09-18 11:28) [25]

так.
И что конкретно ты ожидаешь от этой функции ?
Опиши как ты себе понимаешь ее работу ..


 
bvv   (2009-09-18 11:42) [26]

struct hostent
{
char FAR * h_name;   // имя хоста
char FAR * FAR * h_aliases;  // дополнительные названия
short h_addrtype;   // тип адреса
short h_length;   // длинна каждого адреса в байтах
char FAR * FAR * h_addr_list; // список адресов
};

Мне нужно имя хоста, если есть имя, значит есть и хост.
Я понимаю, что структуру можно и не получить даже если хост физически работает.


 
Сергей М. ©   (2009-09-18 11:59) [27]


> Мне нужно имя хоста


У хоста может не быть имени, от этого он хостом быть не перестанет.


> если есть имя, значит есть и хост


Нет.
Если есть имя, значит есть адрес хоста, а не хост.

Во-первых, ф-ции gethostbyaddr() нет никакого дела до того, присутствует ли хост в сети в момент ее вызова. Она к интересующему хосту не обращается вообще.

Во-вторых, ф-ция gethostbyaddr() позиционируется в Майкрософт как устаревшая, вместо нее настоятельно рекомендуется использовать протоколонезависимую ф-цию getnameinfo(), хотя суть использования новой или старой функции неизменна.

Так что до синхронизации тебе еще как до Китая - ты в принципе не понимаешь что творишь и как это в действительности работает.


 
bvv   (2009-09-18 12:04) [28]

Спасибо, буду разбираться.
С уважением, В


 
Сергей М. ©   (2009-09-18 12:18) [29]

Простая ассоциация для наведения порядка в голове:
Наличие у тебя или кого-либо в адресной книге (читай - база данных DNS) в мобильном телефоне записи
"Имя: Вася Пупкин (читай - HostName), Телефон: 123456789 (читай - HostAddress)"
не означает:

- что Вася Пупкин жив;
- что у него есть телефон;
- что в телефоне установлена симка именно на номер 123456789;
- что владелец телефона и симки в дан.момент именно Вася Пупкин;
- что телефон этот включен;
- что на этот телефон можно позвонить и дозвониться;
- что ответит именно Вася Пупкин и никто иной.


 
Сергей М. ©   (2009-09-18 12:30) [30]

И еще: за массированное сканирование хостов и сервисов можно и по шее получить от провайдера)


 
bvv   (2009-09-18 12:37) [31]

Хорошо, я понял что запрос идёт на DNS.
Пусть в этом вотросе я полный ноль.
Согласен, это действительно не далеко от истины.

Но, почему при разном сисле потоков получаю разное число хостов, хотя запускаются одновременнодве программы, и таблица хостов на DNS не должна так быстро меняться?
Кроме того, повторное сканирование с малым числом потоков 512 точно повторяет предыдущий результат?
Я понимаю если бы результат сканирования 512 и 1792 потока отличался на единицы, но речь идёт о разах. 3-4 раза
Даже если опрос по этой функции даёт полный бред, то почему в одном случае этот бред повторяется с точностью до хоста, а во втором случае нет.
Почему при сканировании локалки, в которой я живу, она точно называет имена и адреса рабочих станций и серверов?

Я не специалист по сетям, и занимаюсь этим, чтобы не отупеть полностью, и не потерять навыки, поскольку решение систем трансцедентных и дифуравнений, при проектировании физических установок в нашей стране уже давно никого не интересут.


 
Сергей М. ©   (2009-09-18 12:57) [32]


> Почему при сканировании


Да нет у тебя никакого сканирования, что ты заладил про сканирование ?)


> локалки, в которой я живу, она точно называет имена и адреса
> рабочих станций и серверов


Потому что эта инф-ция имеется и доступна в тех DNS-базах, к которым ты осуществляешь обращение при своем т.н. "сканировании".

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

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


 
Сергей М. ©   (2009-09-18 13:01) [33]


> не специалист по сетям


Придется в той или иной минимум необходимой мере им стать, если ты действительно желаешь осознать происходящее.
И это, скажем, не самое худшее лекарство от отупения)


 
bvv   (2009-09-18 13:07) [34]


>
> Придется в той или иной минимум необходимой мере им стать,
>  если ты действительно желаешь осознать происходящее.
> И это, скажем, не самое худшее лекарство от отупения)
> <Цитата>


Соглосен на все сто.

Удачи Вам!
В


 
Сергей М. ©   (2009-09-18 13:09) [35]

Точнее, сканирование-то есть, но сканируешь ты вовсе не то, что заявил в топикстарте: ты просто тупо шаришь по записям доступных тебе DNS-рерурсов.


 
Сергей М. ©   (2009-09-18 13:15) [36]

Ключевой момент, могущий пролить свет на тайну: сетевые DNS-сервисы работают под управлением транспортного протокола UDP, который не гарантирует доставку инф.сообщений от источника к приемнику.
И чем "дальше" от твоего хоста находится хост, предоставляющий DNS-сервис, тем меньше вероятность достоверности получаемых при DNS-запросах данных.


 
bvv   (2009-09-18 13:31) [37]

Да, я читал об UDP и других протоколах, назначение их тоже для меня более или менее ясно, Олифера прочитал и общая картина сети понятна, но теория без практики пустое место, пока своими руками что-то не сделаешь, нечего и говорить о том, что знаешь. Телефонный справочник может быть и интересное чтиво, особенно на ночь, но если нет телефона или некуда звонить...
То же и с сетями, надо пробовать и порверять.
Но потоки всё-таки, можно рассматривать и без глубокого понимания работы сети, мне почему-то так кажется...
Но может быть я не прав.


 
Сергей М. ©   (2009-09-18 14:01) [38]


> потоки всё-таки, можно рассматривать и без глубокого понимания
> работы сети, мне почему-то так кажется


Правильно кажется.
Более того, на этом этапе их следовало бы рассматривать в полном отрыве от сетевой логики.
Т.е. мухи отдельно (потоки, синхронизация и т.д. и т.п.), а котлеты отдельно (сети, протоколы и т.д. и т.п).
И уж только тогда следует сажать мух на котлеты, когда мухи станут большими-злыми-зелеными-осенними, а котлеты будут хорошо прожарены)

О чем я тебе и сказал в [32] (про эмулятор)


 
bvv   (2009-09-18 14:11) [39]

Понял.

До свидания.
Разберусь с сетями вернусь.
Конец связи.
В


 
Anatoly Podgoretsky ©   (2009-09-18 15:25) [40]

> bvv  (17.09.2009 17:12:08)  [8]

Поэтому и неверно вешать блок на один поток, пока он ждет ответа от несуществуеющего ИП, то остальные тоже ждут, а могли бы работать, если бы поток занимался только одним ИП. Результат может быть очень существенным, по сути равным обработке одного потока, даже если все ИП не существуют. Ну а класс С взят просто как удобная величина, поскольку обычно пингуют не больше одного класса за раз, на самом деле никакой связи с классами нет, это может произвольный список и количество потоков не обязательно 256, может эффективнее будет 512. Все будет зависить от количества адресов. Но и в этом случае один поток может обслужить 100 адресов, пока другой поток ждет ответа. И не надо потоки постоянно создавать разрушать, достаточно пула потоков.



Страницы: 1 2 вся ветка

Форум: "Сети";
Текущий архив: 2012.03.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.59 MB
Время: 0.004 c
1-1286692304
Lex_!
2010-10-10 10:31
2012.03.11
Работа с элементами IE


15-1321628043
Dimka Maslov
2011-11-18 18:54
2012.03.11
Баг или фича


15-1321469110
wl
2011-11-16 22:45
2012.03.11
На хабрахабре открыта регистрация


15-1321220394
KilkennyCat
2011-11-14 01:39
2012.03.11
TCanvas &amp; HTML


2-1322641073
_qwerty_
2011-11-30 12:17
2012.03.11
работа с bookmark





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский