⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udiiocpsocketserver.pas

📁 楠楠写的DBiocp例子都是源码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
var
  lingerStrt: TLinger;
  m_bDisconnect: Boolean;
begin
  if Assigned(FClientChannel) then begin
    FClientChannel.FContextLock.Lock;
    m_bDisconnect := FClientChannel.FSocket <> INVALID_SOCKET;
    FClientChannel.FContextLock.UnLock;

    if m_bDisconnect then begin
      lingerStrt.l_onoff := 1;
      lingerStrt.l_linger := 0;
      FClientChannel.FContextLock.Lock;
      WinSock2.setsockopt( FClientChannel.FSocket,
                           SOL_SOCKET,
                           SO_LINGER,
                           @lingerStrt,
                           sizeof(lingerStrt) ) ;
      Winsock2.closesocket(FClientChannel.FSocket);
      FClientChannel.FSocket := INVALID_SOCKET;
      FClientChannel.FClosed := TRUE;
      FClientChannel.FContextLock.UnLock;
    end;
  end;
end;

procedure TDITcpSocketServer.DisconnectAllClient;
var
  FClientChannel: TDIClientChannel;
begin
  //FHasMapLock.Lock;
  repeat
    FClientChannel := FHasMapClientChannel.GetTopClientChannel;
    if FClientChannel<> nil then begin
      DisconnectClient(FClientChannel);
      FClientChannel.FContextLock.Lock;
      AppendErrorMessage(Format('DisconnectAllClient->DisconnectClient, Key: %d.',
                       [FClientChannel.m_KeyID]));
      FClientChannel.FContextLock.UnLock;
    end;
  until FClientChannel = nil;
  //FHasMapLock.UnLock;

  AppendErrorMessage(Format('DisconnectAllClient: 空闲池数:%d, 上下文数:%d.',
                     [m_PoolClientChannel.GetClientChannelCount,
                     FHasMapClientChannel.GetClientChannelCount]));
end;

procedure TDITcpSocketServer.FreeAllClientChannel;
begin
  m_PoolClientChannel.FreeClientChannels;
end;

procedure TDITcpSocketServer.ParseIOError(FClientChannel: TDIClientChannel; FBuffer: TDIBuffer; dwIoSize: DWORD);
var
  bClosed: Boolean;
  iRecv, iSend: Integer;
begin
 // FHasMapLock.Lock;
 {
  FClientChannel.FContextLock.Lock;
  iRecv := FClientChannel.m_ReadSequenceNumber;
  iSend := FClientChannel.m_SendSequenceNumber;
  bClosed := FClientChannel.FClosed;
  FClientChannel.FContextLock.UnLock;


  if (iRecv = 0) and (iSend = 0) then
  begin
    if not bClosed then begin
      DisconnectClient(FClientChannel);
      AppendErrorMessage(Format('ParseIOError->DisconnectClient, Key: %d.',
                       [FClientChannel.m_KeyID]));

      FClientChannel.FContextLock.Lock;
      if Assigned(OnCloseSocketEvent) then OnCloseSocketEvent(FClientChannel);
      FClientChannel.FContextLock.UnLock;
    end
    else
    begin
      //从上下文件队列中移出,并且加入回收池中
      FHasMapClientChannel.RemoveClientChannel(FClientChannel.m_KeyID);
      m_PoolClientChannel.ReleaseClientChannelToPool(FClientChannel);

      AppendErrorMessage( Format('ParseIOError: 空闲池数:%d, 上下文数:%d.',
                          [m_PoolClientChannel.GetClientChannelCount,
                          FHasMapClientChannel.GetClientChannelCount]) );  
    end;        
  end
  else
    AppendErrorMessage('FClientChannel.m_ReadSequenceNumber:'+ IntToStr(iRecv)+
                       'FClientChannel.m_SendSequenceNumber:'+ IntToStr(iSend));
  //FHasMapLock.unLock;
end;  

                

         }


{
function TDITcpSocketServer.AssociateIncomingClientWithContext(AcceptExBuffer: TDIBuffer): Boolean;
var
  nRet: Integer;
  bVal: LongBool;
  LocalAddrP, RemoteAddrP: PSockAddr;
  LocalAddrLen, RemoteAddrLen: Integer;
  FClientChannel: TDIClientChannel;
begin
  //系统退出或设置未连接状态,则关闭客户端SOCKET
  if (m_bShutDown) or (not m_bAcceptConnections) then begin
    AppendErrorMessage('m_bShutDown OR not m_bAcceptConnections, 关闭客户端连接.');
    Winsock2.closesocket(AcceptExBuffer.m_Socket);
    AcceptExBuffer.m_Socket := INVALID_SOCKET;
    Result := FALSE;
    Exit;
  end;

 	//是否超过最大连接数:
	if( m_iNumberOfActiveConnections > m_iMaxNumConnections ) then begin
    AppendErrorMessage(Format('客户端已经达到最大连接数: %d, 关闭客户端连接.', [m_iMaxNumConnections]));
    Winsock2.closesocket(AcceptExBuffer.m_Socket);
    AcceptExBuffer.m_Socket := INVALID_SOCKET;
    Result := FALSE;
    Exit;
  end;

  if (AcceptExBuffer.m_Socket = INVALID_SOCKET) then begin
    AppendErrorMessage(Format('m_Scket = INVALID_SOCKET, AssociateIncomingClientWithContext退出: %d.', [WSAGetLastError()]));
    Result := FALSE;
    Exit;
  end;

  //从空闲池中分配一个上下文
  FClientChannel := m_PoolClientChannel.AllocateFreeClientChannelFromPool;
  if not Assigned(FClientChannel) then begin
    AppendErrorMessage(Format('FPoolClientChannel.AllocateFreeClientChannelFromPool错误: %d.', [WSAGetLastError()]));
    Result := FALSE;
    Exit;
  end;

  //设置Socket, KeyID, 得到客户端IP地址
  FClientChannel.FSocket := AcceptExBuffer.m_Socket;
  FClientChannel.m_KeyID := FClientChannel.FSocket;
  //获取客户端IP地址
  GetAcceptExSockaddrs( AcceptExBuffer.GetBuffer,
                        0,
                        sizeof(TSockAddrIn)+16,
                        sizeof(TSockAddrIn)+16,
                        LocalAddrP,
                        LocalAddrLen,
                        RemoteAddrP,
                        RemoteAddrLen );
  FClientChannel.FLocalAddr := LocalAddrP^;
  FClientChannel.FRemoteAddr := RemoteAddrP^;
  
  //禁止nagle算法
  bVal := TRUE;
  nRet := Winsock2.setsockopt( FClientChannel.FSocket,
                               IPPROTO_TCP,
                               TCP_NODELAY,
                               PChar(@bVal),
                               SizeOf(bVal) );
  if (nRet = SOCKET_ERROR) then begin
    AppendErrorMessage(Format('setsockopt(禁止nagle算法) 错误: %d.',[WSAGetLastError()]));
    Winsock2.closesocket(FClientChannel.FSocket);
    FClientChannel.FSocket := INVALID_SOCKET;
    //回收上下文
    m_PoolClientChannel.ReleaseClientChannelToPool(FClientChannel);
    Result := FALSE;
    Exit;
  end;

  //客户上下文插入上下文管理中。
  if FHasMapClientChannel.AddClientChannel( FClientChannel.m_KeyID,
                                            FClientChannel ) then begin
    //关联完成端口
    if m_IOCompletionPort.AssociateSocketWithCompletionPort( FClientChannel.FSocket,
                                                             DWORD(Pointer(FClientChannel)) ) then
    begin
      //连接数加1, 投递Recv I/O 操作,接收客户端数据。
      Inc(m_iNumberOfActiveConnections);
      //触发客户端连接事件
      if Assigned(OnNewSocketEvent) then OnNewSocketEvent(FClientChannel);
      PostWSARecv(FClientChannel);
      Result := TRUE;
    end
    else
    begin
      AppendErrorMessage(Format('m_IOCompletionPort.AssociateSocketWithCompletionPort失败: %d.',[WSAGetLastError()]));
      //触发客户端断开事件
      OnCloseSocketEvent(FClientChannel);
      DisconnectClient(FClientChannel);

      FHasMapClientChannel.RemoveClientChannel(FClientChannel.m_KeyID);
      m_PoolClientChannel.ReleaseClientChannelToPool(FClientChannel);
      Result := FALSE;
      Exit;
    end;
  end
  else
  begin
    AppendErrorMessage(Format('m_MapClientChannel.AddClientChannel失败: %d.',[WSAGetLastError()]));
    //触发客户端断开事件
    OnCloseSocketEvent(FClientChannel);
    DisconnectClient(FClientChannel);
    m_PoolClientChannel.ReleaseClientChannelToPool(FClientChannel);
    Result := FALSE;
    Exit;
  end;

end;

function TDITcpSocketServer.PostWSARecv(FClientChannel: TDIClientChannel): Boolean;
var
  nRet: integer;
  dwIOSize: DWORD;
  dwFlags: DWORD;
begin
  if Assigned(FClientChannel) then begin
    FClientChannel.FContextLock.Lock;

    FClientChannel.RecvBuffer.InitBuffer;
    FClientChannel.RecvBuffer.SetOperation(IOWSARecv);
    FClientChannel.RecvBuffer.SetupRead;
    dwIOSize := 0;
    dwFlags := 0;

    nRet := WinSock2.WSARecv( FClientChannel.FSocket,
                              @FClientChannel.RecvBuffer.FWSABuf,
                              1,
                              dwIOSize,
                              dwFlags,
                              @FClientChannel.RecvBuffer.PerHandleData,
                              nil );

     if( ( nRet = SOCKET_ERROR ) and ( WSAGetLastError() <> WSA_IO_PENDING ) ) then begin
        FClientChannel.FContextLock.UnLock;
			  PostWSACloseSocket(FClientChannel);
			  Result := FALSE;
        Exit;
     end;

     //加一 接受加1
     Inc(FClientChannel.m_ReadSequenceNumber);
     FClientChannel.FContextLock.UnLock;
  end;

  Result := TRUE;
end;


function TDITcpSocketServer.OnWSARecv(FClientChannel: TDIClientChannel; FRecvBuffer: TDIBuffer; dwIoSize: DWORD): Boolean;
begin
  if Assigned(FClientChannel) then begin
    FClientChannel.FContextLock.Lock;
    if Assigned(OnReadCompletedEvent) then
      OnReadCompletedEvent(FClientChannel, FRecvBuffer);
    FClientChannel.FContextLock.UnLock;

    //投递下一个Buffer
    PostWSARecv(FClientChannel);
  end;
 
  Result := TRUE;
end;

function TDITcpSocketServer.PostWSASend(FClientChannel: TDIClientChannel): Boolean;
var
  nRet: integer;
  dwIOSize: DWORD;
  dwFlags: DWORD;
begin
  if Assigned(FClientChannel) then begin
    FClientChannel.FContextLock.Lock;

    FClientChannel.SendBuffer.SetOperation(IOWSASend);
    FClientChannel.SendBuffer.SetupWrite;
    dwIOSize := 0;
    dwFlags := 0;

    nRet := WinSock2.WSASend( FClientChannel.FSocket,
                              @FClientChannel.SendBuffer.FWSABuf,
                              1,
                              dwIOSize,
                              dwFlags,
                              @FClientChannel.SendBuffer.PerHandleData,
                              nil );

     if( ( nRet = SOCKET_ERROR ) and ( WSAGetLastError() <> WSA_IO_PENDING ) ) then begin
       FClientChannel.FContextLock.UnLock;
			 PostWSACloseSocket(FClientChannel);
       Result := FALSE;
       Exit;
     end;

     //加一 发送加1
     Inc(FClientChannel.m_SendSequenceNumber);
     FClientChannel.FContextLock.UnLock;
  end;

  Result := TRUE;
end;


function TDITcpSocketServer.OnWSASend(FClientChannel: TDIClientChannel; FSendBuffer: TDIBuffer; dwIoSize: DWORD): Boolean;
begin
  if Assigned(FClientChannel) then begin
    FClientChannel.FContextLock.Lock;

    if Assigned(OnWriteCompletedEvent) then
      OnWriteCompletedEvent(FClientChannel, FSendBuffer);
    FClientChannel.FContextLock.UnLock;
  end;
 
  Result := TRUE;
end;




procedure TDITcpSocketServer.StopServer;
begin    {
  if (m_bServerStarted) then begin
    //是否允许客户端连接
		m_bAcceptConnections := FALSE;
    AppendErrorMessage('m_bAcceptConnections := FALSE.');
    //关闭所有连接
		DisconnectAllClient;
    AppendErrorMessage('DisconnectAllClient成功.');

    //关闭侦听套接字
    WinSock2.shutdown(m_sListen, SD_BOTH);
    CloseSocket(m_sListen);
    m_sListen := INVALID_SOCKET;
    AppendErrorMessage('关闭侦听套接字成功.');
    FreeAndNil(FAcceptExBuffer);
    AppendErrorMessage('释放FAcceptExBuffer.');
    m_bServerStarted := FALSE;
  end;    
end;     }

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -