//子线程函数
function ChildThrd(p:Pointer):LongInt;stdcall;
Const
RecvSize=102400;
var
PkLen:integer;
ThreadId:integer;
ASocket:TSocket;
buf:array[0..102400] of char;
IntRe:integer;
a,b:pChar;
IdHTTP: TIdHTTP;
StrTest:string; BufRecv:pchar;
StrList:TStringList;//测试 StrArrRe:Array [0..19] of String;
StrMobileNumber,StrPwd:String;
begin
Result:=-1;
ThreadId:=TParam(p^).TrdId;
ASocket:=TParam(p^).Sckt;
Writeln('Thread '+IntToStr(ThreadId)+' Create'); FillChar(buf,SizeOf(buf),0);
PkLen:=Recv(ASocket,buf,SizeOf(buf),0); //接收数据 //拆分客户端传来的(日志、Tuxedo请求)信息A|B|C
SplitString(StrArrRe,buf,'|');
GetMem(BufRecv,RecvSize); //分配发送空间
ZeroMemory(bufRecv,RecvSize); //初始化空间
if(SameText(StrArrRe[0],'Tuxedo')) then
begin
StrMobileNumber:=StrArrRe[1];
StrPwd:=StrArrRe[2]; IntRe:=-9999;
IntRe:=User_Auth(pChar(StrMobileNumber),pChar(StrPwd));
Writeln('result is :' +StrMobileNumber+'::'+inttostr(IntRe));
StrPCopy(bufRecv,inttostr(IntRe));
Send(ASocket,bufRecv^,Length(bufRecv),0);//发送数据
end
else
begin
//-------------------------------------------------
IdHTTP:= TIdHTTP.Create(nil);
//StrTest:='http://172.18.14.139/proxychmp/detail/detailsms.jsp?devno=15311060280&startday=20090301&endday=20090330&lang=cn'; ZeroMemory(bufRecv,RecvSize);
StrPCopy(bufRecv,IdHTTP.Get(buf));
IdHTTP.Free;
if PkLen>0 then
begin
Send(ASocket,bufRecv^,Length(bufRecv),0);//发送数据
end;
end;
Writeln(buf);
CloseSocket(ASocket); //关闭socket
Dispose(p);
FreeMem(BufRecv);
Writeln('Thread '+IntToStr(ThreadId)+' End');
Writeln('Socket '+IntToStr(ASocket)+' DisConnect');
end;
主程序收到客户端请求后,会创建一个子线程ChildThrd来处理客户端请求。为什么同时有多个客户并发访问时,就会出现地址冲突?导致服务程序直接异常退出?
function ChildThrd(p:Pointer):LongInt;stdcall;
Const
RecvSize=102400;
var
PkLen:integer;
ThreadId:integer;
ASocket:TSocket;
buf:array[0..102400] of char;
IntRe:integer;
a,b:pChar;
IdHTTP: TIdHTTP;
StrTest:string; BufRecv:pchar;
StrList:TStringList;//测试 StrArrRe:Array [0..19] of String;
StrMobileNumber,StrPwd:String;
begin
Result:=-1;
ThreadId:=TParam(p^).TrdId;
ASocket:=TParam(p^).Sckt;
Writeln('Thread '+IntToStr(ThreadId)+' Create'); FillChar(buf,SizeOf(buf),0);
PkLen:=Recv(ASocket,buf,SizeOf(buf),0); //接收数据 //拆分客户端传来的(日志、Tuxedo请求)信息A|B|C
SplitString(StrArrRe,buf,'|');
GetMem(BufRecv,RecvSize); //分配发送空间
ZeroMemory(bufRecv,RecvSize); //初始化空间
if(SameText(StrArrRe[0],'Tuxedo')) then
begin
StrMobileNumber:=StrArrRe[1];
StrPwd:=StrArrRe[2]; IntRe:=-9999;
IntRe:=User_Auth(pChar(StrMobileNumber),pChar(StrPwd));
Writeln('result is :' +StrMobileNumber+'::'+inttostr(IntRe));
StrPCopy(bufRecv,inttostr(IntRe));
Send(ASocket,bufRecv^,Length(bufRecv),0);//发送数据
end
else
begin
//-------------------------------------------------
IdHTTP:= TIdHTTP.Create(nil);
//StrTest:='http://172.18.14.139/proxychmp/detail/detailsms.jsp?devno=15311060280&startday=20090301&endday=20090330&lang=cn'; ZeroMemory(bufRecv,RecvSize);
StrPCopy(bufRecv,IdHTTP.Get(buf));
IdHTTP.Free;
if PkLen>0 then
begin
Send(ASocket,bufRecv^,Length(bufRecv),0);//发送数据
end;
end;
Writeln(buf);
CloseSocket(ASocket); //关闭socket
Dispose(p);
FreeMem(BufRecv);
Writeln('Thread '+IntToStr(ThreadId)+' End');
Writeln('Socket '+IntToStr(ASocket)+' DisConnect');
end;
主程序收到客户端请求后,会创建一个子线程ChildThrd来处理客户端请求。为什么同时有多个客户并发访问时,就会出现地址冲突?导致服务程序直接异常退出?
//看你写的代码,真是头晕!
//出错的原因可能是因为没有进行线程同步
//我修改了一下你的程序
TDispatchThread = class(TThread)
private { Private declarations }
procedure DispatchRequest();
procedure CreateSubThread();
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
end;
procedure TDispatchThread.DispatchRequest;
begin
CreateSubThread;
end; procedure TDispatchThread.CreateSubThread;
var
thd: TThdJobThread;
begin
thd:= TThdSubJob.Create(TRUE);
thd.FreeOnTerminate := TRUE;
thd.Resume;
end;//TThdJobThread类
uses
SyncObjs;
TThdJobThread= class(TThread)
private
procedure DotheJob;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
end; procedure TThdJobThread.DotheJob;
begin
ChildThrd;//lz的代码
end;
procedure TThdJobThread.Execute;
begin
JobExec.Acquire;
try
DotheJob;
finally
JobExec.Release;
end;
end;
initialization
JobExec := TCriticalSection.Create; finalization
JobExec.Free;
program t_Server;{$APPTYPE CONSOLE}uses
SysUtils,
Winsock,
Windows,
IdHTTP,
Classes;type
TParam=record
TrdId:integer;
Sckt:TSocket;
end; function User_Auth(cMobileNumber:pChar;cPwd :pChar ):integer;cdecl;
external 'Tuxedo_Auth.dll';
{按照ch分割字符串Source,并存储在arstr中}
function SplitString(var arstr: array of string; const Source: string; ch: Char): integer;
var
i, head: Integer;
begin
result := 0; if Source = '' then
begin
arstr[1] := '';
inc(result);
exit;
end; head := 1;
for i := 1 to length(Source) do
begin
if Source[i] = ch then
begin
arstr[result] := copy(Source, head, i - head);
head := i + 1;
inc(result);
end;
end;
arstr[result] := copy(Source, head, length(Source) - head + 1);
inc(result);
end;
/////////////////////////////////////////////////////////////////////////////
//子线程函数
function ChildThrd(p:Pointer):LongInt;stdcall;
Const
RecvSize=102400;
var
PkLen:integer;
ThreadId:integer;
ASocket:TSocket;
buf:array[0..102400] of char;
//StrArrRe:Array [0..19] of String;
IntRe:integer;
a,b:pChar;
IdHTTP: TIdHTTP;
StrTest:string; BufRecv:pchar;
StrList:TStringList;//测试 StrArrRe:Array [0..19] of String;
StrMobileNumber,StrPwd:String;
begin
Result:=-1;
ThreadId:=TParam(p^).TrdId;
ASocket:=TParam(p^).Sckt;
Writeln('Thread '+IntToStr(ThreadId)+' Create'); FillChar(buf,SizeOf(buf),0);
PkLen:=Recv(ASocket,buf,SizeOf(buf),0); //接收数据 //拆分客户端传来的(日志、Tuxedo请求)信息A|B|C
SplitString(StrArrRe,buf,'|');
GetMem(BufRecv,RecvSize); //分配发送空间
ZeroMemory(bufRecv,RecvSize); //初始化空间
if(SameText(StrArrRe[0],'Tuxedo')) then
begin
StrMobileNumber:=StrArrRe[1];
StrPwd:=StrArrRe[2]; IntRe:=-9999;
IntRe:=User_Auth(pChar(StrMobileNumber),pChar(StrPwd));
Writeln('result is :' +StrMobileNumber+'::'+inttostr(IntRe));
StrPCopy(bufRecv,inttostr(IntRe));
Send(ASocket,bufRecv^,Length(bufRecv),0);//发送数据
end
else
begin
//-------------------------------------------------
IdHTTP:= TIdHTTP.Create(nil); ZeroMemory(bufRecv,RecvSize);
StrPCopy(bufRecv,IdHTTP.Get(buf)); IdHTTP.Free;
if PkLen>0 then
begin
Send(ASocket,bufRecv^,Length(bufRecv),0);//发送数据
end;
end;
Writeln(buf);
CloseSocket(ASocket); //关闭socket
Dispose(p);
FreeMem(BufRecv);
Writeln('Thread '+IntToStr(ThreadId)+' End');
Writeln('Socket '+IntToStr(ASocket)+' DisConnect');
end;//主程序
var
MyWSA: WSAData;
Svr,Clt: TSockAddr;
NameLen:Integer;
hSocket,s: TSocket;
TimeOut:integer;
ThreadCount:integer;
hThread:Thandle;
ThreadID:DWord;
Param:^TParam;
begin
If WSAStartup(MAKEWORD(2,2), MyWSA) <> 0 Then //初始化
Begin
WSACleanup;
Writeln('WSAStartup() Fail');
Exit;
end;
hSocket := Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建socket
If hSocket = INVALID_SOCKET Then
Begin
WSACleanup;
Writeln('Socket() Fail');
Exit;
End;
Svr.sin_family := AF_INET;
Svr.sin_port := htons(9999); //server端口号为9999
Svr.sin_addr.S_addr := inet_addr(PChar('10.12.252.251'));//server的ip地址为127.0.0.1
If Bind(hSocket, Svr, SizeOf(Svr)) = SOCKET_ERROR Then //绑定socket
Begin
CloseSocket(hSocket);
WSACleanup;
Writeln('Bind() Fail');
Exit;
end;
if Listen(hSocket,256) = SOCKET_ERROR Then //socket开始侦听,最大同时连接数为256个
begin
CloseSocket(hSocket);
WSACleanup;
Writeln('Listen() Fail');
Exit;
end;
TimeOut:=3000;
ThreadCount:=0;
Writeln('Listening......');
while true do
begin
NameLen:=SizeOf(Clt);
s:=Accept(hSocket,@Clt,@NameLen);//接受一个连接
if s = SOCKET_ERROR Then
begin
CloseSocket(hSocket);
WSACleanup;
Writeln('Accept() Fail');
Exit;
end
else
begin
Writeln('Socket '+IntToStr(s)+' Connect');
if SetSockOpt(s,SOL_SOCKET,SO_RCVTIMEO,PChar(@TimeOut),SizeOf(TimeOut))=SOCKET_ERROR then //设置接收超时为3秒
begin
CloseSocket(s);
CloseSocket(hSocket);
WSACleanup;
Writeln('SetSockOpt() Fail');
Exit;
end;
if SetSockOpt(s,SOL_SOCKET,SO_SNDTIMEO,PChar(@TimeOut),SizeOf(TimeOut))=SOCKET_ERROR then //设置发送超时为3秒
begin
CloseSocket(s);
CloseSocket(hSocket);
WSACleanup;
Writeln('SetSockOpt() Fail');
Exit;
end;
new(Param);
Param^.TrdId:=ThreadCount;
Param^.Sckt:=s;
hThread:=CreateThread(nil,0,@ChildThrd,Param,0,ThreadID); //创建childthrd子线程
if hThread=0 then
begin
Writeln('CreateThread() Fail');
end
else
begin
Inc(ThreadCount);
end;
end;
end;
CloseSocket(hSocket); //关闭socket
WSACleanup;
end.