服务端的工作方式为阻塞,当客户端有连接时就启动一个线程,如果客户端关闭socket时服务端如何知道并关闭相应的socket

解决方案 »

  1.   

    服务器端是启动时就打开socket,并不是为每一个客户端而打开,所以不能随客户端关闭socket而服务器关闭相应的socket。但如果是最后一个客户端关闭socket的话,可以通过OnClientDisconnect事件来检测到如果没有客户端连接服务器,服务器可以断开,下面是一个例子为你参考:procedure TFrmMCS.ServerSocket1ClientDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      ClientConnectCount: integer;
      con: integer;
    begin
        ClientConnectCount := ServerSocket1.Socket.ActiveConnections;
        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';
       if ClientConnectCount < 1 then
         ServerSocket1.Active := false;
    end;
      

  2.   

    韦利谢谢你,我还想问
    如果假设已有一个客户端连接上,但在下一个客户端连接前我如何把前一个连接关闭呢,
    我用的是阻塞式
    连接SOCKET的代码并启动线程的代码如下
    procedure TForm1.DataServerSocketGetThread(Sender: TObject;
      ClientSocket: TServerClientWinSocket;
      var SocketThread: TServerClientThread);
    begin
        SocketThread := TSendDataThread.Create(False, ClientSocket);
    end;
    谢谢你能给我答复
      

  3.   

    还有好象服务端工作在阻塞方式下不会响应
    ServerSocket1ClientDisconnect(Sender:TObject; Socket: TCustomWinSocket);
      

  4.   

    是的,不会相应该事件,我也提过这个问题,已经OVER:
    ---------------------------------------------------
    主  题:  Socket 的多线程编程求救!!! 分不够再加!! 
    作  者:  errorcode (errorcode)  
    等  级:    
    信 誉 值:  100 
    所属论坛:  Delphi 网络编程/分布式开发 
    问题点数:  100 
    回复次数:  5 
    发表时间:  2003-04-03 12:46:01 
       
     
       
    我该怎么办呢?他已经困扰我多日了。
    请各位大侠指点。谢了我用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。
    我该怎么办呢?他已经困扰我多日了。
    请各位大侠指点。谢了
      
     
     
     回复人: errorcode(errorcode) ( ) 信誉:100  2003-04-03 12:49:00  得分:0 
     
     
      我该怎么办呢?他已经困扰我多日了。
    请各位大侠指点。谢了
      
     
    Top 
     
     回复人: errorcode(errorcode) ( ) 信誉:100  2003-04-03 15:08:00  得分:0 
     
     
      高人,帮帮我吧!
      
     
    Top 
     
     回复人: Wally_wu(韦利) ( ) 信誉:101  2003-04-03 17:25:00  得分:0 
     
     
      怎么会呢,你的代码是正确的!
    通常,如果每个客户端的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;  
     
    Top 
     
     回复人: rcy() ( ) 信誉:100  2003-04-03 18:01:00  得分:0 
     
     
      在服務器端的ClientError中:ErrorCode:=0;
    這樣服務器端不會死掉了。而且會自動結束和客戶端的連接並復位。
      
     
    Top 
     
     回复人: errorcode(errorcode) ( ) 信誉:100  2003-04-03 18:03:00  得分:0 
     
     
      谢谢,
    我已经找到原因了。
    是我对SOCKet的编程还不熟悉,我看了TWinSocketStream的源代码。WaitForData其实是调用了IO复用Select。所以只要将Stream.WaitForData(3000) 中的时间值调整到一个很大的值就可以了,这样就能在没有数据传送的时候,线程阻塞在WaitForData,当有数据传送时,WaitForData返回,然后调用Stream.Read读取数据,如果读出数据长度为0,表示客户端关闭,如果数据长度不是0,表示使正常数据传送。