Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.16;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.051 c
8-1077368857
able
2004-02-21 16:07
2004.05.16
сравнение картинок


14-1082574712
Kme
2004-04-21 23:11
2004.05.16
Качалки


14-1083007266
GEN++
2004-04-26 23:21
2004.05.16
Раскинем карты и ...... погадаем.


1-1083158410
snake1977
2004-04-28 17:20
2004.05.16
Порты


9-1073263023
Чюня
2004-01-05 03:37
2004.05.16
OpenGL