var i:integer; SocketTest: TServerSocket; begin result:=8800; SocketTest:=TServerSocket.Create(Owner); SocketTest.Active:=true; for i:=8800 to 9800 do begin socketTest.Close; SocketTest.Port:=i; try SocketTest.Open; SocketTest.Close; SocketTest.Active:=false; result:=i; exit; except end; end; 很久以前的一个东西,这位前辈似乎现在还在csdn工作……
Procedure TMainForm.SetStuffOnOff(Const St:Boolean); Begin IsRunning:=St; StopBtn.Enabled:=St; StartBtn.Enabled:=Not St; If Not (St) Then Begin ActivityLB.Items.Add('Done Scanning ' + IPAddressE.text); StatusL.Caption:='Status:' End End;
Procedure TMainForm.WSsocketConnect(Sender: TObject; Socket: TCustomWinSocket); Begin //socket connection made //port must be open! ActivityLB.Items.Add('PORT: ' + inttostr(PortX) + '; OPEN!');
If (IsRunning) Then If (PortX > MaxPort) Then SetStuffOnOff(False) Else wsSocket.Active := True //test the new port End;
Procedure TMainForm.WSsocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; Var ErrorCode: Integer); Begin //connection failed.... ErrorCode:=0; //handle the error If Not (OpenOnlyCB.Checked) Then ActivityLB.Items.Add('Port: ' + inttostr(PortX) + '; Closed.');
//try next port wsSocket.Active := False; //close it PortX := PortX + 1; //new port to check wsSocket.Port := PortX; //put the port in the socket StatusL.Caption:='Scanning port:['+IntToStr(PortX)+']';
If (IsRunning) Then If (PortX > MaxPort) Then SetStuffOnOff(False) Else wsSocket.Active := True //test the new port End;
Procedure TMainForm.StopBtnClick(Sender: TObject); Begin SetStuffOnOff(False); wssocket.Active := False; ActivityLB.Items.Add('Stoped scan; port ' + inttostr(PortX) + '!') End;
Procedure TMainForm.FormCreate(Sender: TObject); Begin IsRunning := False End;
End. 这个全面一些
gyk120 的代码调试起来很不方便,能不能把你的窗体代码也贴出来?右击窗体,选择“View as text”可看到窗体代码。
问题解决了,用阻塞的办法,设置了超时时间//分端口扫描线程函数 function ThreadScan(P:pointer):Longint;stdcall; var PPortPart : PTPortPart; i : DWORD; ret : Integer; strtimeout : String; ul : integer; fdread : TFDSET; timeout : Timeval; s : TSocket; ServerAddr : TSockAddr; TempNode : TTreeNode; begin PPortPart := PTPortPart(P); //扫描端口 for i:= PPortPart.FirstPort to (PPortPart.FirstPort+PPortPart.PortCount-1) do begin s := Socket(AF_INET, SOCK_STREAM, 0); if (s = INVALID_SOCKET) then //Socket创建失败 begin showmessage(inttostr(WSAGetLastError())+' Socket创建失败'); CloseSocket(s); end; if(setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,@strtimeout,sizeof(strtimeout))=SOCKET_ERROR) then begin closesocket(s); continue; end; if(setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,@strtimeout,sizeof(strtimeout))=SOCKET_ERROR) then begin continue; end; ul := 1; ret := ioctlsocket(s, FIONBIO, ul); if(ret=SOCKET_ERROR) then begin closesocket(s); continue; end; ZeroMemory(@ServerAddr,sizeof(ServerAddr)); ServerAddr.sin_addr.s_addr:=inet_addr(PChar(PPortPart.strIp)) ; //目标IP ServerAddr.sin_family := AF_INET; ServerAddr.sin_port := htons(i); connect(s,ServerAddr,sizeof(ServerAddr)); //连接 timeout.tv_sec := 0; timeout.tv_usec := 2000; FD_ZERO(fdread); FD_SET(s,fdread); ret := select(0, nil, @fdread, nil, @timeout); if ( ret <= 0 ) then begin CloseSocket(s); continue; end; CloseSocket(s); //将扫描到的开放端口加入TreeView控件TV_PortInfo ZeroMemory(@TempNode,sizeof(TempNode)); TempNode := PortScanFrm.TV_PortInfo.Items.AddChild(PortScanFrm.GetNode,inttostr(i)); TempNode.ImageIndex := 2; TempNode.SelectedIndex := 2; {if (Trim(TempNode.Text)=Trim(PortScanFrm.TV_PortInfo.Items.Item[TempNode.Index-1].Text)) then begin PortScanFrm.TV_PortInfo.Items.Item[TempNode.Index-1].Delete; end;} end; end;
i:integer;
SocketTest: TServerSocket;
begin
result:=8800;
SocketTest:=TServerSocket.Create(Owner);
SocketTest.Active:=true;
for i:=8800 to 9800 do
begin
socketTest.Close;
SocketTest.Port:=i;
try
SocketTest.Open;
SocketTest.Close;
SocketTest.Active:=false;
result:=i;
exit;
except
end;
end;
很久以前的一个东西,这位前辈似乎现在还在csdn工作……
Interface
Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp;
Type
TMainForm = Class(TForm)
LblIPAddress: TLabel;
IPAddressE: TEdit;
lblScanRange: TLabel;
MinPortE: TEdit;
lblPorttoport: TLabel;
MaxPortE: TEdit;
StatusL: TLabel;
ActivityLB: TListBox;
StartBtn: TButton;
WSsocket: TClientSocket;
StopBtn: TButton;
OpenOnlyCB: TCheckBox;
Procedure StartBtnClick(Sender: TObject);
Procedure WSsocketConnect(Sender: TObject; Socket: TCustomWinSocket);
Procedure WSsocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; Var ErrorCode: Integer);
Procedure StopBtnClick(Sender: TObject);
Procedure FormCreate(Sender: TObject);
Private
{ Private declarations }
PortX, MaxPort:Integer;
IsRunning:Boolean;
Procedure SetStuffOnOff(Const St:Boolean);
Public
{ Public declarations }
End;
Var
MainForm: TMainForm;
Implementation
{$R *.dfm}
Procedure TMainForm.SetStuffOnOff(Const St:Boolean);
Begin
IsRunning:=St;
StopBtn.Enabled:=St;
StartBtn.Enabled:=Not St;
If Not (St) Then
Begin
ActivityLB.Items.Add('Done Scanning ' + IPAddressE.text);
StatusL.Caption:='Status:'
End
End;
Procedure TMainForm.StartBtnClick(Sender: TObject);
Begin
ActivityLB.Items.Clear;
PortX := StrToInt(MinPortE.text);
MaxPort := StrToInt(MaxPortE.text);
wsSocket.Address := IPAddressE.text;
wsSocket.Port := PortX;
wsSocket.Active := True;
SetStuffOnOff(True);
ActivityLB.Items.Add('Beginning scan: ' + IPAddressE.text)
End;
Procedure TMainForm.WSsocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
Begin
//socket connection made
//port must be open!
ActivityLB.Items.Add('PORT: ' + inttostr(PortX) + '; OPEN!');
//try next port...
wsSocket.Active := False;
PortX := PortX + 1;
wsSocket.Port := PortX;
StatusL.Caption:='Scanning port:['+IntToStr(PortX)+']';
If (IsRunning) Then
If (PortX > MaxPort) Then
SetStuffOnOff(False)
Else
wsSocket.Active := True //test the new port
End;
Procedure TMainForm.WSsocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; Var ErrorCode: Integer);
Begin
//connection failed....
ErrorCode:=0; //handle the error
If Not (OpenOnlyCB.Checked) Then
ActivityLB.Items.Add('Port: ' + inttostr(PortX) + '; Closed.');
//try next port
wsSocket.Active := False; //close it
PortX := PortX + 1; //new port to check
wsSocket.Port := PortX; //put the port in the socket
StatusL.Caption:='Scanning port:['+IntToStr(PortX)+']';
If (IsRunning) Then
If (PortX > MaxPort) Then
SetStuffOnOff(False)
Else
wsSocket.Active := True //test the new port
End;
Procedure TMainForm.StopBtnClick(Sender: TObject);
Begin
SetStuffOnOff(False);
wssocket.Active := False;
ActivityLB.Items.Add('Stoped scan; port ' + inttostr(PortX) + '!')
End;
Procedure TMainForm.FormCreate(Sender: TObject);
Begin
IsRunning := False
End;
End.
这个全面一些
function ThreadScan(P:pointer):Longint;stdcall;
var
PPortPart : PTPortPart;
i : DWORD;
ret : Integer;
strtimeout : String;
ul : integer;
fdread : TFDSET;
timeout : Timeval;
s : TSocket;
ServerAddr : TSockAddr;
TempNode : TTreeNode;
begin
PPortPart := PTPortPart(P);
//扫描端口
for i:= PPortPart.FirstPort to (PPortPart.FirstPort+PPortPart.PortCount-1) do
begin
s := Socket(AF_INET, SOCK_STREAM, 0);
if (s = INVALID_SOCKET) then //Socket创建失败
begin
showmessage(inttostr(WSAGetLastError())+' Socket创建失败');
CloseSocket(s);
end;
if(setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,@strtimeout,sizeof(strtimeout))=SOCKET_ERROR)
then begin
closesocket(s);
continue;
end;
if(setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,@strtimeout,sizeof(strtimeout))=SOCKET_ERROR)
then begin
continue;
end;
ul := 1;
ret := ioctlsocket(s, FIONBIO, ul);
if(ret=SOCKET_ERROR)
then begin
closesocket(s);
continue;
end;
ZeroMemory(@ServerAddr,sizeof(ServerAddr));
ServerAddr.sin_addr.s_addr:=inet_addr(PChar(PPortPart.strIp)) ; //目标IP
ServerAddr.sin_family := AF_INET;
ServerAddr.sin_port := htons(i);
connect(s,ServerAddr,sizeof(ServerAddr)); //连接
timeout.tv_sec := 0;
timeout.tv_usec := 2000;
FD_ZERO(fdread);
FD_SET(s,fdread);
ret := select(0, nil, @fdread, nil, @timeout);
if ( ret <= 0 )
then begin
CloseSocket(s);
continue;
end;
CloseSocket(s);
//将扫描到的开放端口加入TreeView控件TV_PortInfo
ZeroMemory(@TempNode,sizeof(TempNode));
TempNode := PortScanFrm.TV_PortInfo.Items.AddChild(PortScanFrm.GetNode,inttostr(i));
TempNode.ImageIndex := 2;
TempNode.SelectedIndex := 2;
{if (Trim(TempNode.Text)=Trim(PortScanFrm.TV_PortInfo.Items.Item[TempNode.Index-1].Text))
then begin
PortScanFrm.TV_PortInfo.Items.Item[TempNode.Index-1].Delete;
end;}
end;
end;