uses utils_hashs var FOnlineContextList : TDHashTable; FOnlineContextList := TDHashTable.Create(10949); procedure TDiocpTcpServer.AddToOnlineList(pvObject: TIocpClientContext); begin FLocker.lock('AddToOnlineList'); try FOnlineContextList.Add(pvObject.FSocketHandle, pvObject); if DataMoniter <> nil then begin DataMoniter.CalcuMaxOnlineCount(FOnlineContextList.Count); end; finally FLocker.unLock; end; end; function TDiocpTcpServer.FindContext(pvSocketHandle:TSocket): TIocpClientContext; {$IFDEF USE_HASHTABLE} {$ELSE} var lvHash:Integer; lvObj:TIocpClientContext; {$ENDIF} begin FLocker.lock('FindContext'); try {$IFDEF USE_HASHTABLE} Result := TIocpClientContext(FOnlineContextList.FindFirstData(pvSocketHandle)); {$ELSE} Result := nil; lvHash := pvSocketHandle and SOCKET_HASH_SIZE; lvObj := FClientsHash[lvHash]; while lvObj <> nil do begin if lvObj.FRawSocket.SocketHandle = pvSocketHandle then begin Result := lvObj; break; end; lvObj := lvObj.FNextForHash; end; {$ENDIF} finally FLocker.unLock; end; end; procedure TDiocpTcpServer.RemoveFromOnOnlineList(pvObject: TIocpClientContext); {$IFDEF USE_HASHTABLE} {$IFDEF DEBUG_ON} var lvSucc:Boolean; {$ENDIF} {$ELSE} var lvHash:Integer; {$ENDIF} begin {$IFDEF USE_HASHTABLE} FLocker.lock('RemoveFromOnOnlineList'); try {$IFDEF DEBUG_ON} lvSucc := FOnlineContextList.DeleteFirst(pvObject.FSocketHandle); Assert(lvSucc); {$ELSE} FOnlineContextList.DeleteFirst(pvObject.FSocketHandle); {$ENDIF} finally FLocker.unLock; end; {$ELSE} FOnlineContextList.remove(pvObject); FLocker.lock('RemoveFromOnOnlineList'); try // hash if pvObject.FPreForHash <> nil then begin pvObject.FPreForHash.FNextForHash := pvObject.FNextForHash; if pvObject.FNextForHash <> nil then pvObject.FNextForHash.FPreForHash := pvObject.FPreForHash; end else begin // first ele lvHash := pvObject.RawSocket.SocketHandle and SOCKET_HASH_SIZE; FClientsHash[lvHash] := pvObject.FNextForHash; if FClientsHash[lvHash] <> nil then FClientsHash[lvHash].FPreForHash := nil; end; finally FLocker.unLock; end; pvObject.FNextForHash := nil; pvObject.FPreForHash := nil; {$ENDIF} end; function TDiocpTcpServer.OnlineClientsCallBack(pvCallBack: TOnContextEvent; pvTag: Integer; pvTagData: Pointer): Integer; var I:Integer; lvBucket: PDHashData; lvContext: TIocpClientContext; begin Result := 0; FLocker.lock('GetOnlineContextList'); try for I := 0 to FOnlineContextList.BucketSize - 1 do begin lvBucket := FOnlineContextList.Buckets[I]; while lvBucket<>nil do begin if lvBucket.Data <> nil then begin lvContext := TIocpClientContext(lvBucket.Data); if lvContext.LockContext(STRING_EMPTY, nil) then try pvCallBack(lvContext, pvTag, pvTagData); Inc(Result); finally lvContext.UnLockContext(STRING_EMPTY, nil); end; end; lvBucket:=lvBucket.Next; end; end; finally FLocker.unLock; end; end; function TDiocpTcpServer.PostBufferToOnlineClients(pvBuf:Pointer; pvLen:Integer; pvCopyBuf: Boolean = true; pvTag: Integer = 0; pvTagData: Pointer = nil): Integer; var I:Integer; lvBucket: PDHashData; lvContext: TIocpClientContext; begin Result := 0; FLocker.lock('GetOnlineContextList'); try for I := 0 to FOnlineContextList.BucketSize - 1 do begin lvBucket := FOnlineContextList.Buckets[I]; while lvBucket<>nil do begin if lvBucket.Data <> nil then begin lvContext := TIocpClientContext(lvBucket.Data); if lvContext.PostWSASendRequest(pvBuf, pvlen, pvCopyBuf, pvTag, pvTagData) then begin Inc(Result); end; end; lvBucket:=lvBucket.Next; end; end; finally FLocker.unLock; end; end;
TCP服务端使用哈希表记录TCP在线客户端。哈希表可以缓存大量在线客户记录,且哈希查找速度非常快。