请问,在serversocket的onserverclienterror事件中,如何处理各种错误。是直接关闭socket还是将errorcode置为0.谢谢

解决方案 »

  1.   

    首先感谢你的回复。现在面临的问题是,服务器运行几个小时后,客户端仍然可以建立tcp连接,但是报文重传比较厉害。几分钟后连接就会断开。怀疑是不是由于在关闭客户端socket时,没有释放相关资源所致。请大侠明示。
      

  2.   

    TServerSocket只是把WinSock API进行了封装,而且使用的是TCP协议,从TCP协议角度看,报文重传是否和客户端有关?TCP能保证发送的数据包是顺序而且准确的。另外楼主:报文重传是通过截包实现的?
      

  3.   


    procedure TServerSockMaster.gOnAccept(Socket: TCustomWinSocket);
    var
      SocketExt: TSocketExt;
      ABuffer: TSockBuffer;
    begin
      Lock;
      try
      {$IFDEF DEBUG_SOCKET_MASTER}
        LogDebug(Format('SockMaster: Accept socket from IP: %s, Port: %u', [Socket.RemoteAddress, Socket.RemotePort]));
      {$ENDIF}    if FSocketList.Count >= FSocketMax then
        begin
        {$IFDEF DEBUG_SOCKET_MASTER}
          LogDebug(Format('SockMaster: Socket count over %u, close it.', [FSocketMax]));
        {$ENDIF}      Socket.Close;
          Exit;     
        end;    // Use idle sokcet.
        if FIdleSocket.Count <> 0 then
        begin
          SocketExt := FIdleSocket.Items[0];
          FIdleSocket.Delete(0);      SocketExt.FSocket := Socket;
          SocketExt.FCreateTime := Now;
          SocketExt.FLastRecv := 0;
        end else
          SocketExt := TSocketExt.Create(Socket);
        
        if SocketExt <> nil then
        begin
          FSocketList.Add(SocketExt);      // Post message to main form to notify socket connected.
          ABuffer := FBufferMaster.GetBuf;
          Assert(ABuffer <> nil);      ABuffer.FSocketHanlde := Socket.Handle;
          ABuffer.FRemoteIP := Socket.RemoteAddress;
          ABuffer.FRemotePort := Socket.RemotePort;
          PostMessage(FHD_RECV, FWM_MSG_STATE, Integer(True), Integer(ABuffer));  {$IFDEF DEBUG_SOCKET_MASTER}
          LogDebug(Format('SockMaster: SocketExt Count is %u', [FSocketList.Count]));
      {$ENDIF}    
        end
        else
        begin
      {$IFDEF DEBUG_SOCKET_MASTER}
          LogDebug('SockMaster: Create SocketExt failed, Close it');
      {$ENDIF}
          Socket.Close;
        end;
      finally
        Unlock;
      end;
    end;procedure TServerSockMaster.gOnDisconnect(Socket: TCustomWinSocket);
    var
      ASocketExt: TSocketExt;
      Index: Integer;
      ABuffer: TSockBuffer;
    begin
      Lock;
      try
      {$IFDEF DEBUG_SOCKET_MASTER}
        LogDebug(Format('SockMaster: Disconnect socket from IP: %s, Port: %u', [Socket.RemoteAddress, Socket.RemotePort]));
      {$ENDIF}    ASocketExt := Lookup(Socket.Handle);
        if ASocketExt = nil then
        begin
          {$IFDEF DEBUG_SOCKET_MASTER}
          LogDebug(Format('SockMaster: Socket from IP: %s, Port: %u Disconnect, but can''t find it in local',
            [Socket.RemoteAddress, Socket.RemotePort]));
          {$ENDIF}
        
          Exit;
        end;    // Delete socketext from working-socket list.
        Index := FSocketList.IndexOf(ASocketExt);
        Assert(Index <> -1);
        FSocketList.Delete(Index);    Assert(ASocketExt <> nil);
        
        // Add socketext to idle list.
        ASocketExt.FSocket := nil;
        ASocketExt.FCreateTime := 0;
        FIdleSocket.Add(ASocketExt);    // Post message to main form to notify socket disconnected.
        ABuffer := FBufferMaster.GetBuf;
        Assert(ABuffer <> nil);
        
        ABuffer.FSocketHanlde := Socket.Handle;
        ABuffer.FRemoteIP := Socket.RemoteAddress;
        ABuffer.FRemotePort := Socket.RemotePort;
        PostMessage(FHD_RECV, FWM_MSG_STATE, Integer(False), Integer(ABuffer));
      finally
        Unlock;
      end;
    end;procedure TServerSockMaster.gOnClientError(Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    begin
      Lock;  LogWarn(Format('Socket(%s:%d) ErrorEvent %u, ErrorCode = %u', [
        Socket.RemoteAddress, Socket.RemotePort, Integer(ErrorEvent), ErrorCode]));  try
        ErrorCode := 0;
        Socket.Close;
      finally
        Unlock;
      end;
    end;procedure TServerSockMaster.gOnRead(Socket: TCustomWinSocket);
    var
      ABuffer: TSockBuffer;
      RecvLength: Integer;
      ASocketExt: TSocketExt;
      Buf: array[0..BUFFER_SIZE-1] of Byte;
    begin
      Lock;
      try 
        ASocketExt := Lookup(Socket.Handle);
        if ASocketExt <> nil then
          ASocketExt.FLastRecv := Now;    if FSockMode = SOCK_MSG_MOD_PCK then
        begin
          RecvLength := Socket.ReceiveLength;
          if RecvLength = 0 then
            Exit;
         
          ABuffer := FBufferMaster.GetBuf;
          Assert(ABuffer <> nil);      if RecvLength > SizeOf(ABuffer.FBuffer) then
          begin
            {$IFDEF DEBUG_SOCKET_MASTER}
              LogError(Format('SockMaster: Recv Data from (%s:%u), Length is %u over %u, close it',
                [Socket.RemoteAddress, Socket.RemotePort, RecvLength, SizeOf(ABuffer.FBuffer)]));
            {$ENDIF}        // TODO: 必须释放缓冲区
            FBufferMaster.PutBuf(ABuffer);
        
            Socket.Close;
            Exit;
          end;       ABuffer.FLength := RecvLength;
          Socket.ReceiveBuf(ABuffer.FBuffer, RecvLength);
          ABuffer.FRemoteIP := Socket.RemoteAddress;
          ABuffer.FRemotePort := Socket.RemotePort;
          ABuffer.FSocketHanlde := Socket.Handle;      {$IFDEF DEBUG_SOCKET_MASTER}
            LogDebug(Format('SockMaster: Recv Data from (%s:%u), Length is %u',
              [Socket.RemoteAddress, Socket.RemotePort, RecvLength]));
          {$ENDIF}      {$IFDEF DEBUG_DUMP}
            dump(PChar(@ABuffer.FBuffer[0]), ABuffer.FLength);
          {$ENDIF}
          
          // 向接收句柄发送消息
          Assert(FHD_RECV <> 0);
          Assert(FWM_MSG_RECV <> 0);
      
          if (FHD_RECV <> 0) and (FWM_MSG_RECV <> 0) then
            PostMessage(FHD_RECV, FWM_MSG_RECV, 0, Integer(ABuffer));
        end
        else if FSockMode = SOCK_MSG_MOD_STREAM then
        begin
          if ASocketExt <> nil then
          begin
            if Socket.ReceiveLength > 0 then
            begin
              RecvLength := Socket.ReceiveBuf(Buf, SizeOf(buf));
              ASocketExt.FRingBuffer.WriteBuffer(Buf, RecvLength);
              
              recvParse(ASocketExt);
            end;
          end;
        end;
      finally
        Unlock;
      end;
    end;
      

  4.   

    上面的代码是对serversocket控件的几个重要事件的响应函数。
    包括
    1. gOnAccept响应ssAccept事件
    2. gOnDisconnect响应ssClientDisconnect事件
    3. gOnClientError响应ssClientError事件
    4. gOnRead响应ssClientRead事件请大侠看看。提供另外个几个信息:
    1. 终端通过gprs同服务器建立tcp连接。
    2. 终端数目为150个。
    3. 客户现场的gprs网络不太稳定。终端在30分钟内未收到来自服务器的数据,就会重新建立连接。
    4. 使用老版本的服务器程序,运行正常。
    5. 使用我新开发的服务器,运行不正常。通过dede,发现,老版本使用的也是serversocket控件,但是却属于scktcomp_6文件,应该是之前的开发人员自己改进的或者引用别人的文件。