Форум: "Сети";
Текущий архив: 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.49 MB
Время: 0.053 c