📄 udiiocpsocketserver.pas
字号:
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 + -