我该怎么办呢?他已经困扰我多日了。
请各位大侠指点。谢了我用D5写了一个Socket的程序,服务器ServerSocket采用stThreadBlocking模式,在ServerSocket.OnGetThread事件中创建一个自己定义的TServerClientThread:
procedure TForm1.ssGetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;
  var SocketThread: TServerClientThread);
begin
    SocketThread:= TSocketCli.Create(ClientSocket);  //(SocketThread);
end;在TSocketCli的ClientExecute方法中执行数据处理(精简):
procedure TSocketCli.ClientExecute;
var
  Stream : TWinSocketStream;
  Buffer : array[0..99] of Char;
begin
    while ((not Terminated) and ClientSocket.Connected) do
    begin
            Stream := TWinSocketStream.Create(ClientSocket, 3000);
            try
                if Stream.WaitForData(3000) then
                begin
                    FillChar(Buffer, 100, 0);
                    if Stream.Read(Buffer, 80) <> 0 then
                    begin
                        Str1:= String(Buffer);
                        Synchronize(GetMsg);
                    end;
                end;
            except
                ;
            end;
            Stream.Free;
        except
            ;
        end;
    end;
end;但是当客户端执行Close后,while ((not Terminated) and ClientSocket.Connected) do 中的ClientSocket.Connected永远为True,导致服务器的线程不能终止,也就是说服务器不能知道Client已经Close。
我该怎么办呢?他已经困扰我多日了。
请各位大侠指点。谢了

解决方案 »

  1.   

    怎么会呢,你的代码是正确的!
    通常,如果每个客户端的Socket关闭后,服务器的ServerSocket会自动Free关闭后的客户端的线程,也就是说,客户端的Socket关闭不会触发ServerSocket的OnGetThread事件。
    其实你可以在ServerSocket的OnClientDisconnect事件上检查Client是否关闭,你可以参考这段代码:
    procedure TFrmMCS.ServerSocket1ClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      ClientConnectCount: integer;
      con: integer;
    begin
        ClientConnectCount := ServerSocket1.Socket.ActiveConnections;
        with RichEdit3 do
        begin
          SelAttributes.Color := clBlack;
          RichEdit3.Refresh;
          Lines.Add(Socket.RemoteHost +' is exist the Chating room');
        end;
        for con := 0 to ServerSocket1.Socket.ActiveConnections -1 do
          if Socket = ServerSocket1.Socket.Connections[con] then
          begin
            ComboBox1.Items.Delete(con);
            ClientConnectCount :=  ClientConnectCount -1;
          end;
        StaticText4.Caption := 'Total ' +inttostr(ClientConnectCount) +'Client(s) Connected Chat Server';
    end;
      

  2.   

    在服務器端的ClientError中:ErrorCode:=0;
    這樣服務器端不會死掉了。而且會自動結束和客戶端的連接並復位。
      

  3.   

    谢谢,
    我已经找到原因了。
    是我对SOCKet的编程还不熟悉,我看了TWinSocketStream的源代码。WaitForData其实是调用了IO复用Select。所以只要将Stream.WaitForData(3000) 中的时间值调整到一个很大的值就可以了,这样就能在没有数据传送的时候,线程阻塞在WaitForData,当有数据传送时,WaitForData返回,然后调用Stream.Read读取数据,如果读出数据长度为0,表示客户端关闭,如果数据长度不是0,表示使正常数据传送。