destructor TAlarmWorkThread.Destroy; begin inherited; end;
procedure TAlarmWorkThread.Execute; var BytesTransferred: DWORD ; PHandleData: LPPerHandelData; Block: PBlock; Flags: DWORD ; BodySize,BytesSend,ErrCode : Integer; Cmd : Word; begin while (not self.Terminated) do begin //查询IOCP状态(数据读写操作是否完成) if (GetQueuedCompletionStatus(FCompletePort, BytesTransferred, DWORD(PHandleData), POverlapped(Block), INFINITE) = true) then begin //FThreadPool.PShowCommGauge(); //工作线程被Post消息提示退出 if (PHandleData = nil) then begin FThreadPool.PShowRealMsg(APP_MSGTYPE_THREAD,'控制信息','报警控制TCP服务器释放相关资源,成功关闭服务!'); Exit; end;
//如果链路断开,释放相关资源 if (BytesTransferred = 0) then begin FThreadPool.PShowRealMsg(APP_MSGTYPE_THREAD,'控制信息','客户端【Addr=' + PHandleData.PSrcAddr + '】'+ PHandleData.PSrcName + '断开,TCP服务器释放相关资源!'); //清除该客户端相关资源 FCloseConnAndFree(PHandleData); Continue; end;
with Block^.Data do try case Block^.Data.OperType of APP_OPERTYPE_RECV: begin FRecAndMakePac(PHandleData,Block,BytesTransferred); Block.Data.IsUse := False; Block.IsUse := False; Block := nil; FReceiveData(PHandleData,Block); Continue; end;
APP_OPERTYPE_SEND: begin Dec(wsaBuffer.len, BytesTransferred); if wsaBuffer.len <= 0 then begin { 发送完成,将Block置空,返回到FBlock的可使用的缓区中 }
//FSendHandlePacByCmd(PHandleData,Block,BytesTransferred); Block.Data.IsUse := False; Block.IsUse := False; Block := nil; end else begin { 数据还没发送完成,继续发送 } Flags := 0; Inc(Pbyte(wsaBuffer.buf), BytesTransferred); FillChar(Overlapped, SizeOf(Overlapped), 0); if SOCKET_ERROR = WSASend( PHandleData.Socket, @wsaBuffer, 1, @BytesSend,Flags, @Overlapped, nil) then begin ErrCode := WSAGetLastError; if ErrCode <> ERROR_IO_PENDING then begin FThreadPool.PShowRealMsg(APP_MSGTYPE_THREAD,'控制信息','客户端【Addr=' + PHandleData.PSrcAddr + '】异常断开,TCP服务器释放相关资源!'); FCloseConnAndFree(PHandleData);//清除该客户端相关资源 Continue; end; end; end; end; end; except end; end else begin if (PHandleData <> nil ) then begin FThreadPool.PShowRealMsg(APP_MSGTYPE_THREAD,'视频服务','客户端【Addr=' + PHandleData.PSrcAddr + '】异常断开,TCP服务器释放相关资源!'); FCloseConnAndFree(PHandleData);//清除该客户端相关资源 end; end; end; end;
function TAlarmWorkThread.FRecAndMakePac(PHandleData: LPPerHandelData;Block: PBlock; Transfered: DWORD): Integer; begin PHandleData.RingBuffer.WriteBuffer(Block.Data.Buffer,Transfered); FCheckisCompletePac(PHandleData); end;
function TAlarmWorkThread.FCheckisCompletePac(PHandleData: LPPerHandelData): Integer; var Tmp:string; PackedLen,BodySize: Word; PackedHead: TNetAlarmHead; dataSize : LongInt; RevBuffer: array [0..MAX_BUFFER_LEN] of Char; WimpPacket: TWimpMsg; cmd:Word; begin dataSize := PHandleData.RingBuffer.GetDataCount(); if dataSize < SizeOf(TNetAlarmHead) then Exit; //如果不够包头长就退出 PHandleData.RingBuffer.Copybuffer(PackedHead,SizeOf(TNetAlarmHead)); cmd := ntohs(PackedHead.Command_Id); PackedLen := FGetLenOfBodyByHeader(cmd); //包体长度 if PackedLen < 0 then begin PHandleData.RingBuffer.Readbuffer(PackedHead,SizeOf(TNetAlarmHead)); FCheckisCompletePac(PHandleData); //嵌套执行 end else begin if dataSize >= (PackedLen + SizeOf(TNetAlarmHead)) then begin PHandleData.RingBuffer.Readbuffer(PackedHead,SizeOf(TNetAlarmHead)); PHandleData.RingBuffer.Readbuffer(RevBuffer,PackedLen); FMergePacked(WimpPacket,cmd,RevBuffer); FHandleRecPacket(WimpPacket,cmd,PHandleData); FCheckisCompletePac(PHandleData); //嵌套执行 end; end; end;
function TAlarmWorkThread.FSendPacket(PHandleData: LPPerHandelData; var HeadBuf,BodyBuf; HeadLen, BodyLen: Integer): Integer; var ErrCode: Integer; Flags, Transfer: Cardinal; Block: PBlock; begin Result := 0; Block := PHandleData.MemoryBuffer.AllocBlock; with Block^.Data do begin Flags := 0; OperType := APP_OPERTYPE_SEND; FillChar(Buffer, SizeOf(Buffer), 0); Move(HeadBuf,Buffer,HeadLen); Move(BodyBuf,Buffer[HeadLen],BodyLen); FillChar(Overlapped, SizeOf(Overlapped), 0); wsaBuffer.buf := @buffer; wsaBuffer.len := HeadLen + BodyLen; if SOCKET_ERROR = WSASend(PHandleData.Socket, @wsaBuffer, 1, @Transfer, Flags, @Overlapped, nil) then begin ErrCode := WSAGetLastError; if ErrCode <> ERROR_IO_PENDING then begin Result := SOCKET_ERROR; end; end; end; end;
function TAlarmWorkThread.FCloseConnAndFree(PHandleData:LPPerHandelData): Integer; var PIoDataID : Integer; Llt : TList; begin Result := 0; PIoDataID := FGetClientID(PHandleData); FThreadPool.PUpdateOnLine(PHandleData.PSrcType,PHandleData.PSrcAddr,False); FThreadPool.PShowRealMsg(APP_MSGTYPE_THREAD,'控制信息','客户端【登录名=' + PHandleData.PSrcAddr + '】'+ PHandleData.PSrcName + '断开,TCP服务器释放相关资源!'); if PIoDataID >=0 then begin FThreadPool.PUpdateCount(PHandleData.PSrcType,APP_UPDATECOUNT_DELETE); Llt := FAlarmSocketLists.LockList(); Llt.Delete(PIoDataID); FAlarmSocketLists.UnlockList; shutdown(PHandleData.Socket,FD_CLOSE); closesocket(PHandleData.Socket); FreeAndNil(PHandleData.MemoryBuffer); FreeAndNil(PHandleData.RingBuffer); GlobalFree(DWORD(PHandleData)); end; end;
function TAlarmWorkThread.FGetClientID(APhandle: LPPerHandelData): integer; var i:Integer; Llt:TList; begin Result := -1; try Llt := FAlarmSocketLists.LockList(); for i:=0 to Llt.Count - 1 Do begin if LPPerHandelData(Llt.Items[i]) = APhandle then begin Result := i; Break; end; end; finally FAlarmSocketLists.UnlockList; end; end;