unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, Buttons,winsock;
type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
SBar: TStatusBar;
procedure FormCreate(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const threadcount=5;
lengthconst=4*1024;
defaulthttpport=80;
listenport=7392;
var serversocket:tsocket;
g_critical:trtlcriticalsection;
pathofprogram:string;
stop:boolean;
filenum:integer;
{$define record}
function socketthread(prt
ointer):integer;stdcall;
type bufarray=array[1..lengthconst] of byte;
var
isa:sockaddr_in;
isa_len:integer;
acceptsocket:tsocket;
targethost
char;
targetport:integer;
rec:file of byte;
str:string[255];
procedure sendbuf(var buf:bufarray;len:integer;sock:tsocket);
var
client:tsocket;
ca:sockaddr_in;
hostinfo
hostent;
hostaddr:u_long;
i:integer;
begin
client:=socket(pf_inet,sock_stream,ipproto_ip);
if client=invalid_socket then
begin
str:=timetostr(now)+'为连接远程服务器创建socket错误!'+#13#10;
blockwrite(rec,str[1],length(Str));
exit;
end;
ca.sin_family:=pf_inet;
ca.sin_port:=htons(targetport);
hostaddr:=inet_addr(targethost);
if (hostaddr=-1) then
begin
hostinfo:=gethostbyname(targethost);
if hostinfo<>nil then
ca.sin_addr:=(pinaddr(hostinfo.h_addr_list^))^
else
begin
str:=timetostr(now)+'主机'+strpas(targethost)+'转换成ip地址错误!'+#13#10;
strdispose(targethost);
blockwrite(Rec,str[1],length(Str));
closesocket(client);
closesocket(sock);
exit;
end;
end
else ca.sin_addr.S_addr:=hostaddr;
strdispose(targethost);
if connect(client,ca,sizeof(ca))<>0 then
begin
str:=timetostr(now)+'连接服务器端socket错误!'+#13#10;
blockwrite(Rec,str[1],length(Str));
closesocket(client);
closesocket(sock);
exit;
end
else
begin
str:=timetostr(now)+'连接服务器端socket成功!'+#13#10;
blockwrite(Rec,str[1],length(Str));
for i:=1 to len do buf
:=not buf;
len:=send(client,buf,len,0);
if len=socket_error then
begin
str:=timetostr(now)+'向服务器端socket发送数据错误!'+#13#10;
blockwrite(Rec,str[1],length(Str));
closesocket(client);
closesocket(sock);
exit;
end;
try
len:=recv(client,buf,lengthconst,0);
while len>0 do
begin
{$ifdef record}
blockwrite(Rec,buf[1],len);
{$endif}
send(sock,buf[1],len,0);
len:=recv(client,buf,lengthconst,0);
end;
finally
if len=socket_error then
str:=timetostr(now)+'从服务器端socket接受数据失败!'+#13#10
else
str:=timetostr(now)+'服务器连接终止!'+#13#10;
blockwrite(rec,str[1],length(str));
closesocket(client);
closesocket(sock);
end;
end;
end;
procedure transmit(sock:tsocket);
function searchsubstr(var buf:bufarray;len:integer)char;
var
pstr,tarstr,posstr,resstrchar;
begin
pstr:=stralloc(len+1);
pstr:=strlcopy(pstr,pchar(@buf[1]),len);
tarstr:=strpos(pstr,#13#10+'host:');
if tarstr=nil then
begin
strdispose(pstr);
result:=nil;
end
else
begin
tarstr:=tarstr+8;
posstr:=strpos(tarstr,#13#10);
if posstr=nil then
begin
strdispose(pstr);
result:=nil;
exit;
end;
resstr:=stralloc(posstr-tarstr+1);
resstr:=strlcopy(resstr,tarstr,posstr-tarstr);
tarstr:=strscan(resstr,';');
if tarstr<>nil then
begin
tarstr:=tarstr+1;
targetport:=strtoint(strpas(tarstr));
result:=strlcopy(resstr,resstr,tarstr-resstr-1);
end
else
result:=resstr;
strdispose(pstr);
end;
end;
var
buf:bufarray;
len:integer;
begin
len:=recv(sock,buf,lengthconst,0);
if len<=0 then
begin
str:=timetostr(now)+'从客户端socket(*'+inttostr(Sock)+'*)接受数据错误!'+#13#10;
blockwrite(Rec,str[1],length(Str));
closesocket(sock);
exit;
end;
str:=timetostr(now)+'从客户端socket(*'+inttostr(Sock)+'*)接受数据!'+#13#10;
blockwrite(Rec,str[1],length(Str));
{$ifdef record}
blockwrite(rec,buf[1],len);
{$endif}
targetport:=defaulthttpport;
targethost:=searchsubstr(buf,len);
if targethost=nil then
begin
str:=timetostr(now)+'为socket(*'+inttostr(sock)+'*)搜寻目标主机产错误!'+#13#10;
blockwrite(rec,str[1],length(Str));
closesocket(sock);
exit;
end;
sendbuf(buf,len,sock);
end;
begin
entercriticalsection(g_critical);
str:=pathofprogram+inttostr(filenum)+'.txt';
assignfile(Rec,str);
rewrite(Rec);
filenum:=filenum+1;
leavecriticalsection(g_critical);
isa_len:=sizeof(isa);
while not stop do
begin
entercriticalsection(g_critical);
acceptsocket:=accept(serversocket,@isa,@isa_len);
leavecriticalsection(g_critical);
if acceptsocket=invalid_socket then
begin
if not stop then
str:=timetostr(now)+'接受客户段错误!'+#13#10
else
str:=timetostr(now)+'接受停止!'+#13#10;
blockwrite(Rec,str[1],length(Str));
continue;
end
else
begin
str:=timetostr(now)+'接收客户端socket';
blockwrite(Rec,str[1],length(Str));
transmit(acceptsocket);
end;
end;
closefile(rec);
filenum:=filenum-1;
result:=0;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
awsadata:twsadata;
begin
if wsastartup($0101,awsadata)<>0 then
begin
messagebox(handle,'不能启动winsock动态链接库!','错误',mb_ok);
exit;
end;
messagebox(handle,awsadata.szsystemstatus,'winsock动态连接库信息',mb_ok);
pathofprogram:=extractfilepath(paramstr(0));
initializecriticalsection(g_critical);
filenum:=1;
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
begin
close;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
var
sa:sockaddr_in;
thandle:hwnd;
i,j:integer;
threadid:dword;
begin
serversocket:=socket(pf_inet,sock_stream,ipproto_ip);
if serversocket=invalid_socket then
begin
messagebox(handle,pchar('创建套接字错误'),pchar('错误'),mb_ok);
exit;
end;
sa.sin_family:=pf_inet;
sa.sin_port:=htons(listenport);
sa.sin_addr.S_addr:=inaddr_any;
if bind(Serversocket,sa,sizeof(sa))=socket_error then
begin
messagebox(handle,pchar('绑定监听socket错误,请检查是否有服务在监听'+inttostr(listenport)+'端口!'),pchar('错误'),mb_ok);
caption:=inttostr(wsagetlasterror);
closesocket(serversocket);
exit;
end;
caption:=caption+'(监听'+inttostr(listenport)+'端口!)';
listen(Serversocket,5);
stop:=false;
for i:=1 to threadcount do
begin
thandle:=createthread(nil,0,@socketthread,nil,0,threadid);
if thandle=0 then
messagebox(handle,pchar('第'+inttostr(i)+'个线程不能创建!'),'提示',mb_ok);
end;
bitbtn2.Enabled:=true;
bitbtn1.Enabled:=false;
sbar.SimpleText:='代理程序执行中!';
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
var
tim:tdatetime;
succ:boolean;
begin
bitbtn2.Enabled:=false;
bitbtn1.Enabled:=false;
form1.Cursor:=crhourglass;
sbar.SimpleText:='正在停止代理程序,请稍后......';
stop:=true;
succ:=true;
if (closesocket(Serversocket)<>0) then
succ:=false;
tim:=now;
while (now-tim<0.0001)and(filenum>1) do
application.ProcessMessages;
if succ then
messagebox(handle,'关闭套接字成功!','提示',mb_ok)
else
messagebox(handle,'关闭监听socket错误!','提示',mb_ok);
bitbtn3.Enabled:=true;
bitbtn1.Enabled:=true;
sbar.SimpleText:='代理程序停止状态';
form1.Cursor:=crdefault;
caption:='winsock api示例----简单http代理';
application.ProcessMessages;
end;
end.
我想知道function socketthread(prtointer):integer;stdcall;在何时编译,因为没有事件调用,还有如何跟踪里面的内容?