//子线程函数
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来处理客户端请求。为什么同时有多个客户并发访问时,就会出现地址冲突?导致服务程序直接异常退出?

解决方案 »

  1.   


    //看你写的代码,真是头晕!
    //出错的原因可能是因为没有进行线程同步
    //我修改了一下你的程序
      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;
      

  2.   

    我把所有的代码都贴出来,帮我看看吧,呵
    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.
      

  3.   

    现在已经知道是内存申请、释放和动态创建控件以及get数据会出导致出现内存冲突问题。但是不知道怎么改