异步端口扫描: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,WInSock, ExtCtrls;const WM_SOCKET=WM_USER+1; //socket消息type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; Panel1: TPanel; Memo1: TMemo; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private Sockhd : integer; //socket句柄 Serv_Addr : Tsockaddr;//目标地址 procedure SockEvent(var msg: Tmessage);message WM_SOCKET; //处理cocket消息 procedure DspMsg(msg : string); //显示信息 { Private declarations } public { Public declarations } end; Form1: TForm1;implementation {$R *.DFM}function lookup_hostname(const hostname:string):longint; //把域名转化成IP地址 var RemoteHost : PHostEnt; (* no, don't free it! *) ip_address: longint; begin ip_address:=-1; try if hostname='' then begin (* no host given! *) lookup_hostname:=ip_address; EXIT; end else begin ip_address:=Winsock.Inet_Addr(PChar(hostname)); (* try a xxx.xxx.xxx.xx first *) if ip_address=SOCKET_ERROR then begin RemoteHost:=Winsock.GetHostByName(PChar(hostname)); if (RemoteHost=NIL) or (RemoteHost^.h_length<=0) then begin lookup_hostname:=ip_address; EXIT; (* host not found *) end else ip_address:=longint(pointer(RemoteHost^.h_addr_list^)^); end; end; except ip_address:=-1; end; lookup_hostname:=ip_address; end;procedure TFOrm1.DspMsg(msg: string); begin memo1.Lines.Add(msg+'...'); if Memo1.Lines.Count>200 then Memo1.Lines.Delete(0); end;procedure TForm1.SockEvent(var msg : tmessage); //处理socket消息 begin case msg.LParam of FD_READ: begin //标识可以读数据,当然肯定已经链接上了 dspmsg('可以读取数据'); //do what you want do end; FD_WRITE: begin dspmsg('可以发送数据'); //do what you want do end; FD_ERROR: begin dspmsg('发生错误'); //如果你是客户端,则应该是连接不上,即端口没有开 end; FD_CLOSE: Begin dspmsg('服务器断开连接'); //对方关闭连接 end; FD_CONNECT: begin dspmsg('连结上服务器'); //表示对方端口开放 end; FD_ACCEPT: begin dspmsg('接收一个请求'); //这个消息只有服务端可能出现 end; end; end;procedure TForm1.FormCreate(Sender: TObject); var wsaData:TwsaData; begin //启动winsock动态链接库 if WSAStartup (makeword(2,2), wsaData)<>0 then begin messagebox(application.handle,'无法启动winsock动态连接库!','警告',MB_OK or MB_APPLMODAL or MB_ICONWARNING); Application.Terminate; end; end;procedure TForm1.FormDestroy(Sender: TObject); begin //关闭dll WSACleanup; end;procedure TForm1.Button1Click(Sender: TObject); begin Sockhd := socket(AF_INET,SOCK_STREAM,0); //创建socket句柄 if Sockhd<0 then begin messagebox(application.handle,'无法创建句柄!','警告',MB_OK or MB_APPLMODAL or MB_ICONWARNING); exit; end; Serv_addr.sin_addr.s_addr:= lookup_hostname(edit1.Text); //主机名 Serv_addr.sin_family := PF_INET; Serv_addr.sin_port := htons(23); //any port you want to connect if WSAAsyncSelect(Sockhd,Form1.handle,WM_SOCKET,FD_ACCEPT or FD_CONNECT or FD_CLOSE or FD_READ or FD_WRITE)=SOCKET_ERROR then begin messagebox(application.handle,'无法创建句柄!','警告',MB_OK or MB_APPLMODAL or MB_ICONWARNING); exit; end; //异步socket connect(sockhd,serv_addr,sizeof(serv_addr)); //连接,结果会在前面的处理函数处理 end;
unit Unit1;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, WinSock, ComCtrls;Const MAXTHREADNUM = 99; FORMTITLE = 'ScanPort '; type TConnect = class(TThread) private { Private declarations } Pos:integer; Port:integer; IP:string; protected procedure Execute; override; procedure Start(p:integer;iPort:integer;ip:string); procedure Update; end;type PerConn=record Conn:TConnect; Active:boolean; end;type TForm1 = class(TForm) Label1: TLabel; Edit1: TEdit; Label2: TLabel; Edit2: TEdit; Button1: TButton; Memo1: TMemo; Button2: TButton; Button3: TButton; Edit4: TEdit; Label3: TLabel; Edit3: TEdit; Label4: TLabel; Button4: TButton; StatusBar1: TStatusBar; procedure Button1Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button2Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } bEnd:boolean; bPause:boolean; public { Public declarations } end;var Form1: TForm1;implementation{$R *.DFM}var ScanPort:array [1..MAXTHREADNUM] of PerConn;procedure TConnect.Execute; var wVersionRequested:word; wsaData:TWSADATA; err:integer; sin:TSockAddrIn; s:TSocket; state:integer; begin { Place thread code here } // if self.Terminated then break; self.Priority :=tpLower ; wVersionRequested := MAKEWORD( 2, 0 ); err := WSAStartup(wVersionRequested, wsaData ); if err <> 0 then begin ShowMessage('Socket Version Error.'); exit; end; s:=Socket(AF_INET,SOCK_STREAM,0); if s=INVALID_SOCKET then begin ShowMessage('Socket Failed.'); exit; end; sin.sin_family :=AF_INET; sin.sin_addr.S_addr :=inet_addr(pchar(ip)); (* with sin.sin_addr.S_un_b do begin s_b1 :=chr(127); s_b2 :=chr(0); s_b3 :=chr(0); s_b4 :=chr(1); end; *) sin.sin_port :=htons(Port); state:=connect(s,sin,sizeof(sin)); if state=0 then begin self.Synchronize(update); end; closesocket(s); WSACleanup(); ScanPort[pos].Active :=false; end;procedure TConnect.Update ; begin form1.Memo1.Lines.Append(inttostr(Port)); end;procedure TConnect.Start(p:integer;iPort:integer;ip:string); begin pos:=p; self.Port :=iPort; self.IP :=ip; self.FreeOnTerminate :=true; self.Resume ; end;//============================================================procedure TForm1.Button1Click(Sender: TObject); var BeginPort,EndPort,ThreadNum:integer; i,j:integer; ip:string;begin try BeginPort:=strtoint(Edit1.Text ); // Get Data if (BeginPort<0 ) or (BeginPort>65535) then begin ShowMessage('Start Port invalid'); exit; end; except on EConvertError do begin ShowMessage('Start Port invalid'); exit; end; end; try EndPort:=strtoint(Edit2.Text ); if (EndPort<0 ) or (EndPort>65535) then begin ShowMessage('End Port invalid'); exit; end; except on EConvertError do begin ShowMessage('End Port invalid'); exit; end; end; try ThreadNum:=strtoint(Edit3.Text); if (ThreadNum<1) or (ThreadNum>99) then begin ShowMessage('0 < ThreadNum < 100'); exit; end; except on EConvertError do begin ShowMessage('Thread Number invalid'); exit; end; end; ip:=Edit4.Text ; //------------------------------ if ip='' then // test ip begin ShowMessage('Error IP Address.'); exit; end; if BeginPort>EndPort then // exchange beginport and endport begin i:=BeginPort; BeginPort:=EndPort; EndPort:=i; end; if ThreadNum>MAXTHREADNUM then begin ThreadNum:=MAXTHREADNUM; end; for j:=1 to MAXTHREADNUM do ScanPort[j].Active :=false; bEnd:=false; bPause:=false; // memo1.Lines.Clear ; button1.Enabled :=false; button2.Enabled :=true; button3.Enabled :=true; Edit1.ReadOnly :=true; Edit2.ReadOnly :=true; Edit3.ReadOnly :=true; Edit4.ReadOnly :=true; StatusBar1.SimpleText :=FORMTITLE +' Running...'; //--------------------------------------------- while BeginPort <= EndPort do begin if bEnd then exit; // end if not bPause then begin for j:=1 to ThreadNum do begin if ScanPort[j].Active =false then break; end; ScanPort[j].Active:=true; ScanPort[j].Conn :=TConnect.Create(true); ScanPort[j].Conn.Start(j,BeginPort,ip); StatusBar1.SimpleText :='Detect: '+inttostr(BeginPort); inc(BeginPort); end; Application.ProcessMessages ; end; // repeat i:=1; for j:=1 to MAXTHREADNUM do begin if ScanPort[j].Active then begin i:=0; break; end; end; application.ProcessMessages; until i=1; Button3Click(sender); end;procedure TForm1.Button3Click(Sender: TObject); var i:integer; b:boolean; begin bEnd:=true; for i:=1 to MAXTHREADNUM do if ScanPort[i].Active then begin ScanPort[i].Conn.Terminate ; end; repeat b:=true; for i:=1 to MAXTHREADNUM do if ScanPort[i].Active then begin b:=false; break; end; application.ProcessMessages; until b; // button1.Enabled :=true; button2.Enabled :=false; button3.Enabled :=false; Edit1.ReadOnly :=false; Edit2.ReadOnly :=false; Edit3.ReadOnly :=false; Edit4.ReadOnly :=false; StatusBar1.SimpleText :=FORMTITLE; end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Button3Click(sender); end;procedure TForm1.Button2Click(Sender: TObject); begin bPause:=not bPause; if bPause then begin StatusBar1.SimpleText :=FORMTITLE +'Pause...'; end else begin StatusBar1.SimpleText :=FORMTITLE; end; end;procedure TForm1.Button4Click(Sender: TObject); begin ShowMessage('HomePage: http://vcshcn.yeah.net/'+#13+'Email: [email protected]'); end;procedure TForm1.FormCreate(Sender: TObject); begin button1.Enabled :=true; button2.Enabled :=false; button3.Enabled :=false; end;end.
[email protected]
谢谢。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,WInSock, ExtCtrls;const WM_SOCKET=WM_USER+1; //socket消息type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Panel1: TPanel;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
Sockhd : integer; //socket句柄
Serv_Addr : Tsockaddr;//目标地址 procedure SockEvent(var msg: Tmessage);message WM_SOCKET; //处理cocket消息
procedure DspMsg(msg : string); //显示信息
{ Private declarations }
public
{ Public declarations }
end; Form1: TForm1;implementation
{$R *.DFM}function lookup_hostname(const hostname:string):longint; //把域名转化成IP地址
var
RemoteHost : PHostEnt; (* no, don't free it! *)
ip_address: longint;
begin
ip_address:=-1;
try
if hostname='' then
begin (* no host given! *)
lookup_hostname:=ip_address;
EXIT;
end
else
begin
ip_address:=Winsock.Inet_Addr(PChar(hostname)); (* try a xxx.xxx.xxx.xx first *)
if ip_address=SOCKET_ERROR then begin
RemoteHost:=Winsock.GetHostByName(PChar(hostname));
if (RemoteHost=NIL) or (RemoteHost^.h_length<=0) then
begin
lookup_hostname:=ip_address;
EXIT; (* host not found *)
end
else
ip_address:=longint(pointer(RemoteHost^.h_addr_list^)^);
end;
end;
except
ip_address:=-1;
end;
lookup_hostname:=ip_address;
end;procedure TFOrm1.DspMsg(msg: string);
begin
memo1.Lines.Add(msg+'...');
if Memo1.Lines.Count>200 then Memo1.Lines.Delete(0);
end;procedure TForm1.SockEvent(var msg : tmessage); //处理socket消息
begin
case msg.LParam of
FD_READ: begin //标识可以读数据,当然肯定已经链接上了
dspmsg('可以读取数据');
//do what you want do
end; FD_WRITE: begin
dspmsg('可以发送数据');
//do what you want do
end; FD_ERROR: begin
dspmsg('发生错误');
//如果你是客户端,则应该是连接不上,即端口没有开
end; FD_CLOSE: Begin
dspmsg('服务器断开连接');
//对方关闭连接
end; FD_CONNECT: begin
dspmsg('连结上服务器');
//表示对方端口开放
end; FD_ACCEPT: begin
dspmsg('接收一个请求');
//这个消息只有服务端可能出现
end;
end;
end;procedure TForm1.FormCreate(Sender: TObject);
var wsaData:TwsaData;
begin //启动winsock动态链接库
if WSAStartup (makeword(2,2), wsaData)<>0 then begin
messagebox(application.handle,'无法启动winsock动态连接库!','警告',MB_OK or MB_APPLMODAL or MB_ICONWARNING);
Application.Terminate;
end;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin //关闭dll
WSACleanup;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
Sockhd := socket(AF_INET,SOCK_STREAM,0); //创建socket句柄
if Sockhd<0 then begin
messagebox(application.handle,'无法创建句柄!','警告',MB_OK or MB_APPLMODAL or MB_ICONWARNING);
exit;
end;
Serv_addr.sin_addr.s_addr:= lookup_hostname(edit1.Text); //主机名
Serv_addr.sin_family := PF_INET;
Serv_addr.sin_port := htons(23); //any port you want to connect if WSAAsyncSelect(Sockhd,Form1.handle,WM_SOCKET,FD_ACCEPT or FD_CONNECT or FD_CLOSE or FD_READ or FD_WRITE)=SOCKET_ERROR
then begin
messagebox(application.handle,'无法创建句柄!','警告',MB_OK or MB_APPLMODAL or MB_ICONWARNING);
exit;
end; //异步socket
connect(sockhd,serv_addr,sizeof(serv_addr)); //连接,结果会在前面的处理函数处理
end;
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, WinSock, ComCtrls;Const MAXTHREADNUM = 99;
FORMTITLE = 'ScanPort ';
type
TConnect = class(TThread)
private
{ Private declarations }
Pos:integer;
Port:integer;
IP:string;
protected
procedure Execute; override;
procedure Start(p:integer;iPort:integer;ip:string);
procedure Update;
end;type PerConn=record
Conn:TConnect;
Active:boolean;
end;type
TForm1 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Edit2: TEdit;
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Button3: TButton;
Edit4: TEdit;
Label3: TLabel;
Edit3: TEdit;
Label4: TLabel;
Button4: TButton;
StatusBar1: TStatusBar;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
bEnd:boolean;
bPause:boolean;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}var ScanPort:array [1..MAXTHREADNUM] of PerConn;procedure TConnect.Execute;
var wVersionRequested:word;
wsaData:TWSADATA;
err:integer;
sin:TSockAddrIn;
s:TSocket;
state:integer;
begin
{ Place thread code here }
// if self.Terminated then break;
self.Priority :=tpLower ;
wVersionRequested := MAKEWORD( 2, 0 ); err := WSAStartup(wVersionRequested, wsaData );
if err <> 0 then
begin
ShowMessage('Socket Version Error.');
exit;
end;
s:=Socket(AF_INET,SOCK_STREAM,0);
if s=INVALID_SOCKET then
begin
ShowMessage('Socket Failed.');
exit;
end;
sin.sin_family :=AF_INET;
sin.sin_addr.S_addr :=inet_addr(pchar(ip));
(* with sin.sin_addr.S_un_b do
begin
s_b1 :=chr(127);
s_b2 :=chr(0);
s_b3 :=chr(0);
s_b4 :=chr(1);
end;
*)
sin.sin_port :=htons(Port);
state:=connect(s,sin,sizeof(sin));
if state=0 then
begin
self.Synchronize(update);
end;
closesocket(s);
WSACleanup();
ScanPort[pos].Active :=false;
end;procedure TConnect.Update ;
begin
form1.Memo1.Lines.Append(inttostr(Port));
end;procedure TConnect.Start(p:integer;iPort:integer;ip:string);
begin
pos:=p;
self.Port :=iPort;
self.IP :=ip;
self.FreeOnTerminate :=true;
self.Resume ;
end;//============================================================procedure TForm1.Button1Click(Sender: TObject);
var BeginPort,EndPort,ThreadNum:integer;
i,j:integer;
ip:string;begin
try
BeginPort:=strtoint(Edit1.Text ); // Get Data
if (BeginPort<0 ) or (BeginPort>65535) then
begin
ShowMessage('Start Port invalid');
exit;
end;
except
on EConvertError do
begin
ShowMessage('Start Port invalid');
exit;
end;
end;
try
EndPort:=strtoint(Edit2.Text );
if (EndPort<0 ) or (EndPort>65535) then
begin
ShowMessage('End Port invalid');
exit;
end;
except
on EConvertError do
begin
ShowMessage('End Port invalid');
exit;
end;
end;
try
ThreadNum:=strtoint(Edit3.Text);
if (ThreadNum<1) or (ThreadNum>99) then
begin
ShowMessage('0 < ThreadNum < 100');
exit;
end;
except
on EConvertError do
begin
ShowMessage('Thread Number invalid');
exit;
end;
end; ip:=Edit4.Text ;
//------------------------------
if ip='' then // test ip
begin
ShowMessage('Error IP Address.');
exit;
end;
if BeginPort>EndPort then // exchange beginport and endport
begin
i:=BeginPort;
BeginPort:=EndPort;
EndPort:=i;
end;
if ThreadNum>MAXTHREADNUM then
begin
ThreadNum:=MAXTHREADNUM;
end;
for j:=1 to MAXTHREADNUM do ScanPort[j].Active :=false;
bEnd:=false;
bPause:=false;
//
memo1.Lines.Clear ;
button1.Enabled :=false;
button2.Enabled :=true;
button3.Enabled :=true;
Edit1.ReadOnly :=true;
Edit2.ReadOnly :=true;
Edit3.ReadOnly :=true;
Edit4.ReadOnly :=true;
StatusBar1.SimpleText :=FORMTITLE +' Running...';
//--------------------------------------------- while BeginPort <= EndPort do
begin
if bEnd then exit; // end
if not bPause then
begin
for j:=1 to ThreadNum do
begin
if ScanPort[j].Active =false then break;
end;
ScanPort[j].Active:=true;
ScanPort[j].Conn :=TConnect.Create(true);
ScanPort[j].Conn.Start(j,BeginPort,ip);
StatusBar1.SimpleText :='Detect: '+inttostr(BeginPort);
inc(BeginPort);
end;
Application.ProcessMessages ;
end;
//
repeat
i:=1;
for j:=1 to MAXTHREADNUM do
begin
if ScanPort[j].Active then
begin
i:=0;
break;
end;
end;
application.ProcessMessages;
until i=1;
Button3Click(sender);
end;procedure TForm1.Button3Click(Sender: TObject);
var i:integer;
b:boolean;
begin
bEnd:=true;
for i:=1 to MAXTHREADNUM do
if ScanPort[i].Active then
begin
ScanPort[i].Conn.Terminate ;
end;
repeat
b:=true;
for i:=1 to MAXTHREADNUM do
if ScanPort[i].Active then
begin
b:=false;
break;
end;
application.ProcessMessages;
until b;
//
button1.Enabled :=true;
button2.Enabled :=false;
button3.Enabled :=false;
Edit1.ReadOnly :=false;
Edit2.ReadOnly :=false;
Edit3.ReadOnly :=false;
Edit4.ReadOnly :=false;
StatusBar1.SimpleText :=FORMTITLE;
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Button3Click(sender);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
bPause:=not bPause;
if bPause then
begin
StatusBar1.SimpleText :=FORMTITLE +'Pause...';
end
else
begin
StatusBar1.SimpleText :=FORMTITLE;
end;
end;procedure TForm1.Button4Click(Sender: TObject);
begin
ShowMessage('HomePage: http://vcshcn.yeah.net/'+#13+'Email: [email protected]');
end;procedure TForm1.FormCreate(Sender: TObject);
begin
button1.Enabled :=true;
button2.Enabled :=false;
button3.Enabled :=false;
end;end.