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

Вниз

Проблема с неблокирующими сокетами.   Найти похожие ветки 

 
rezya ©   (2004-03-25 20:07) [0]

Привет вам о могучие мастера Delphi. Вот пытаюсь что то навоять, типа сканера портов но наталкиваюсь на одну проблему.
При сканировании обычным сканером, не моим, у меня открыты 7 портов а своим пишет только что 5, в чем проблема?
Причем к примеру 5 открыты с 1 по 2000 порт а ещё 2 с 3000 по ... И если задать сканирование с 3000 адреса то он их увидит.
Такое ощущение что массива PFdSet.Fd_count и PFdSet.fd_array расчитаны только на 5 элементов. Приведу код дабы было все понятно. Делаю в отдельно процессе.

var
   k,i,a:integer;
   Fd : PFdSet;
   SizeOfPort:Integer;

procedure WWW.Execute;
Var
Data,data1:WsaData;
Sock,Sock1:TSocket;
Addr,Addr1:sockaddr_in;
TmVal:TTimeVal;
Result:string;
begin
FreeOnTerminate:=True;
if (WSAStartup($202,Data) <> 0)then  Synchronize(WSAStartup1);
SizeOfPort:=(EndPort-StartPort)+1;
TmVal.tv_sec:=1;
TmVal.tv_usec:=0;
GetMem(Fd, SizeOfPort*sizeof(Fd^.fd_array[0])+sizeof(Fd^.fd_count));
A:=1;
try
FD_ZERO(Fd^);
ZeroMemory(@Addr, sizeof(Addr));
Addr.sin_family:=AF_INET;
Addr.sin_addr.S_addr:=inet_Addr(PChar(IpAdress));
Synchronize(Message1);

For K:=StartPort to EndPort do
begin
   Addr.sin_port:=htons(k);
   Sock := socket(AF_INET, SOCK_STREAM, 0);
   if (Sock <> INVALID_SOCKET) then
   begin
     if  (ioctlsocket(Sock, FIONBIO, a) = SOCKET_ERROR)
      or ((connect(Sock, Addr, SizeOf(Addr)) = SOCKET_ERROR)
           and (WSAGetLastError <> WSAEWOULDBLOCK)
         ) then
     begin
        Synchronize(count);
       closesocket( Sock );
     end else
     begin
       FD.fd_array[FD^.fd_count] := Sock;
       Inc(FD^.fd_count);
     end;
   end;
 end;
{-------------------------------}
if Fd^.fd_count = 0 then
   exit;
 select(FD^.fd_count, nil, Fd, nil, @TmVal);
Synchronize(Message2);
 For K := 0 to Fd^.fd_count-1  do
 begin
   if FD_ISSET(FD^.fd_array[K],Fd^) then
   begin
     I := sizeof(Addr);
     if getpeername( FD^.fd_array[K], Addr, I ) <> SOCKET_ERROR then
     a:=ntohs(Addr.sin_port);
     Synchronize(Good);
   end;
   closesocket(FD^.fd_array[K]);
 end;
finally
 FreeMem(Fd);
Synchronize(End_Scan);
end;

Жду предложений....


 
Verg ©   (2004-03-25 21:03) [1]

Потому, что select ждет до первого же попавшегося события.
Ты взял исходник поисковика сервера - там оно и надо было: достаточно было дождаться первого же соединения. Т.е. принцип - "любой, у которого открыт порт"
А сканер надо делать иначе. "Все, у которых открыт".

Чувствуешь разницу?

Тебе просто повезло, что 5 портов откликнулись почти одновременно. Могло быть и один.


 
rezya ©   (2004-03-26 00:59) [2]

Хорошо понял. Но а как реализовать второй вариант "Все, у которых открыт порт".


 
rezya ©   (2004-03-26 12:28) [3]

Что то я попробовал реализовать такую концепцию но ничего не получилось. Что посоветуешь?


 
Digitman ©   (2004-03-26 13:08) [4]


> попробовал реализовать такую концепцию но ничего не получилось


показывай как "пробовал"


 
Verg ©   (2004-03-26 16:53) [5]

Да все тоже самое, только в цикле.

Также понадбится 3 FDS-а: один эталонный, один для WriteFDS и один для ExceptFDS.
При составленнии эталонного FDS-а, после connect() == SOCKET_ERROR надо контролировать WSAGelAstError на предмет WSAENOBUFS, и если он случился, то закончить составлять эталонный набор, запомнив порт, на котором ядру не хватило буферов для следующей итерации.

До селекта копируешь эталонный FDS в оба Write и Except
Вызываешь селект
После селекта
проверяешь набор WriteFDS и сработавшие дескрипторы (порт открыт) заносишь в список портов, затем удаляешь его из эталноого FDS-а
Проверяешь набор ExceptFDS-ов и все в нем сработавшие просто удаляешь из эталноого FDS-а
Не забываешь закрфвать сокеты (а то, кхем,....систему посадишь)
И так все в цикле.


 
Verg ©   (2004-03-26 17:03) [6]

Что-нибудь в таком духе:

function PortScanner( const Address : string;
                     StartPort,
                     EndPort : word;
                     TimeOut : integer) : string;
var
Addr:TSockAddr;
Fd, Fds, Fde : PFdSet;
I, K : integer;
uK : u_long;

TmVal:TTimeVal;

SetSize : integer;
S : TSocket;
FStartPort : word;

begin
Result := "";
if StartPort = 0 then
  StartPort := 1;
SetSize := (EndPort - StartPort) + 1;
if SetSize <= 0 then
  exit;
SetSize := SetSize*sizeof(Fd^.fd_array[0])+sizeof(Fd^.fd_count);
ZeroMemory(@Addr, sizeof(Addr));
Addr.sin_family:=AF_INET;
Addr.sin_addr.S_addr:= inet_addr(pchar(Address));
uK:=1;
TmVal.tb_sec:=TimeOut;
TmVal.tv_usec:=0;

GetMem(Fd,  SetSize);
GetMem(Fds, SetSize);
GetMem(Fde, SetSize);
try
repeat
  FD_ZERO(Fds^);
  FStartPortt := 0;
  S := INVALI_SOCKET;
  For i:=StartPort to EndPort do
  begin
    if S<>INVALID_SOCKET then
      closesocket(S);
    S := socket(AF_INET, SOCK_STREAM, 0);
    Addr.sin_port:=htons(word(i));
    if (S <> INVALID_SOCKET) then
    begin
      if  ioctlsocket(S, FIONBIO, uK) <> SOCKET_ERROR then
      begin
        if connect(S, Addr, SizeOf(Addr)) = SOCKET_ERROR then
        begin
          if WSAGetLastError = WSAENOBUFS then
          begin
            closeSocket(S);
            FStartPort := i;
            break
          end;
          if WSAGetLastError <> WSAEWOULDBLOCK then
            continue;
        end;
        FDs^.fd_array[FDs^.fd_count] := S;
        Inc(FDs^.fd_count);
        S:=INVLID_SOCKET;
      end;
    end;
  end;
  while Fds^.fd_count <> 0 do
  begin
    move(Fds^, Fd^, SetSize);
    move(Fds^, Fde^, SetSize);
    sRet := select(FD^.fd_count, nil, Fd, Fde, @TmVal);
    if (sRet <= 0)  then
      break;
    for K := 0 to Fd^.fd_count-1  do
    if FD_ISSET( FD^.fd_array[K], Fd^ ) then
    begin
      I := sizeof(Addr);
      if getpeername( FD^.fd_array[K], Addr, I ) <> SOCKET_ERROR then
        Result := Result + IntToStr(ntohs(Addr.sin_poft)) + " ";
      FD_CLR(FD^.fd_array[K], Fds^);
      closesocket(FD^.fd_array[K]);
    end;
    for K := 0 to Fde^.fd_count-1  do
    if FD_ISSET( FDe^.fd_array[K], Fde^ ) then
    begin
      FD_CLR(FDe^.fd_array[K], Fds^);
      closesocket(FDe^.fd_array[K]);
    end;
  end;
  For K := 0 to Fds^.fd_count-1  do
    closesocket(FDs^.fd_array[K]);
  if FStartPort = 0 then Break;
  StartPort := FStartPort;
until False;
finally
   FreeMem(Fd);
   FreeMem(Fds);
   FreeMem(Fde);
end;
end;


 
rezya ©   (2004-03-26 20:09) [7]

Спасибо за пример но есть пару вопросов по поводу функций и переменных, которые ты используешь, где про них можно почитать:
FD_ISSET
FD_CLR
Fd_SetSize


 
Verg ©   (2004-03-26 20:29) [8]

Там же, где обычно:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/select_2.asp


 
rezya ©   (2004-03-26 20:38) [9]

А на русском :-))


 
Verg ©   (2004-03-26 21:18) [10]


> rezya ©   (26.03.04 20:38) [9]
> А на русском :-))


А не слишком ли много хочешь :-))


 
Rezya ©   (2004-03-26 23:59) [11]

Попробовал эту концепцию все нормально заработало но только один вопрос?
Почему весь процес проходит так сказать с тормозами? Т.Е. Доходит до определенного момента и потом ждет чегото потом дальше продолжает?


 
Verg ©   (2004-03-27 00:10) [12]


> концепцию


Это не концепция - это просто кодинг. Что там тормозит - попробуй разобраться сам. Это я тебе не из медвежьих побуждений советую - это тебе самому нужно (наверно).

Кстати, а что, скомпилировалось и заработало, что ли?


 
Rezya ©   (2004-03-27 00:20) [13]

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


 
Rezya ©   (2004-03-27 00:20) [14]

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


 
Piter ©   (2004-03-27 15:55) [15]

В 9x нельзя открыть более 255 сокетов, поэтому там могут быть тормоза... а вот в XP не знаю



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

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

Наверх





Память: 0.5 MB
Время: 0.027 c
3-1082106946
Smile))
2004-04-16 13:15
2004.05.16
Конвертация БД


1-1082651546
Vitalnet
2004-04-22 20:32
2004.05.16
Увидеть весь тект в выподающем меню


6-1080161810
Pr0t0n
2004-03-24 23:56
2004.05.16
SMS &amp; Delphi


14-1083027022
MPS
2004-04-27 04:50
2004.05.16
Какого пингвина выбрать ???


11-1069729742
azsd
2003-11-25 06:09
2004.05.16
KOLThread puzzle me...some code works incroctly in/out of Thread.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский