本文整理自网络,侵删。
Delphi的跨平台框架FireMonkey下的TCP组件默认自带INDY的,但我个人在使用某些特别的库的时候喜欢再封装一层,封装为简单的对外公开的接口,这里分享一下基于indy的封装的tcp的请求的库。以下代码基于Delphi 10.2。
{ 单元名:跨平台的TCP客户端库封装 作者:5bug 网站:http://www.5bug. wang }unit uCPTcpClient;interfaceuses System.Classes, System.SysUtils, IdTCPClient, IdGlobal;type TOnRevDataEvent = procedure(const pData: Pointer; const pSize: Cardinal) of object; TCPTcpClient = class private FConnected: Boolean; FHost: string; FPort: Integer; FOnRevDataEvent: TOnRevDataEvent; FOnDisconnectEvent: TNotifyEvent; type TTcpThreadType = (tt_Send, tt_Recv, tt_Handle); TCPTcpThread = class(TThread) private FOnExecuteProc: TProc; protected procedure Execute; override; public property OnExecuteProc: TProc read FOnExecuteProc write FOnExecuteProc; end; TTcpDataRecord = class(TMemoryStream); protected FTCPClient: TIdTCPClient; FSendDataList: TThreadList; FRecvDataList: TThreadList; FCahceDataList: TThreadList; FTcpThread: array [TTcpThreadType] of TCPTcpThread; procedure InitThread; procedure FreeThread; procedure ExcuteSendProc; procedure ExcuteRecvProc; procedure ExcuteHandleProc; procedure ExcuteDisconnect; procedure ClearData; function PushToSendCahce(const AData: Pointer; const ASize: NativeInt): Boolean; public constructor Create(); destructor Destroy; override; procedure InitHostAddr(const AHost: string; const APort: Integer); function TryConnect: Boolean; procedure DisConnect; function Send(const AData: Pointer; const ASize: NativeInt): Boolean; property Connected: Boolean read FConnected; property Host: string read FHost; property Port: Integer read FPort; property OnRevDataEvent: TOnRevDataEvent read FOnRevDataEvent write FOnRevDataEvent; property OnDisconnectEvent: TNotifyEvent read FOnDisconnectEvent write FOnDisconnectEvent; end;implementationuses uLogSystem;{ TCPTcpClient }procedure TCPTcpClient.ClearData;var I: Integer; ADataRecord: TTcpDataRecord;begin with FSendDataList.LockList do try for I := 0 to Count - 1 do begin ADataRecord := Items[I]; FreeAndNil(ADataRecord); end; Clear; finally FSendDataList.UnlockList; end; with FRecvDataList.LockList do try for I := 0 to Count - 1 do begin ADataRecord := Items[I]; FreeAndNil(ADataRecord); end; Clear; finally FRecvDataList.UnlockList; end; with FCahceDataList.LockList do try for I := 0 to Count - 1 do begin ADataRecord := Items[I]; FreeAndNil(ADataRecord); end; Clear; finally FCahceDataList.UnlockList; end;end;constructor TCPTcpClient.Create;begin FTCPClient := TIdTCPClient.Create(nil); FTCPClient.ConnectTimeout := 5000; FTCPClient.ReadTimeout := 5000; InitThread;end;destructor TCPTcpClient.Destroy;begin FreeThread; FTCPClient.Free; inherited;end;procedure TCPTcpClient.DisConnect;begin ExcuteDisconnect;end;procedure TCPTcpClient.ExcuteDisconnect;begin FConnected := False; FTCPClient.DisConnect; if MainThreadID = CurrentThreadId then begin if Assigned(FOnDisconnectEvent) then FOnDisconnectEvent(Self); end else begin TThread.Synchronize(FTcpThread[tt_Recv], procedure begin if Assigned(FOnDisconnectEvent) then FOnDisconnectEvent(Self); end); end;end;procedure TCPTcpClient.ExcuteHandleProc;var I: Integer; ADataRecord: TTcpDataRecord;begin // 不要长时间锁住收数据的列队 with FRecvDataList.LockList do try while Count > 0 do begin ADataRecord := Items[0]; FCahceDataList.Add(ADataRecord); Delete(0); end; finally FRecvDataList.UnlockList; end; with FCahceDataList.LockList do try while Count > 0 do begin ADataRecord := Items[0]; Delete(0); TThread.Synchronize(FTcpThread[tt_Handle], procedure begin if Assigned(FOnRevDataEvent) then FOnRevDataEvent(ADataRecord.Memory, ADataRecord.Size); FreeAndNil(ADataRecord); end); end; finally FCahceDataList.UnlockList; end;end;procedure TCPTcpClient.ExcuteRecvProc;var ADataRecord: TTcpDataRecord; ADataSize: Integer;begin if FConnected then begin try FTCPClient.Socket.CheckForDataOnSource(1); ADataSize := FTCPClient.IOHandler.InputBuffer.Size; if ADataSize > 0 then begin ADataRecord := TTcpDataRecord.Create; with FRecvDataList.LockList do try Add(ADataRecord); finally FRecvDataList.UnlockList; end; FTCPClient.Socket.ReadStream(ADataRecord, ADataSize); end; FTCPClient.Socket.CheckForDisconnect(False, True); except ExcuteDisconnect; end; end; Sleep(1);end;function TCPTcpClient.PushToSendCahce(const AData: Pointer; const ASize: NativeInt): Boolean;var ADataRecord: TTcpDataRecord;begin Result := False; if FConnected then begin ADataRecord := TTcpDataRecord.Create; ADataRecord.Write(AData^, ASize); with FSendDataList.LockList do try Add(ADataRecord); finally FSendDataList.UnlockList; end; Result := True; end;end;procedure TCPTcpClient.ExcuteSendProc;var ADataRecord: TTcpDataRecord;begin if FConnected then begin ADataRecord := nil; with FSendDataList.LockList do try if Count > 0 then begin ADataRecord := Items[0]; Delete(0); end; finally FSendDataList.UnlockList; end; if ADataRecord <> nil then begin FTCPClient.IOHandler.Write(ADataRecord); FreeAndNil(ADataRecord); end; end; Sleep(1);end;procedure TCPTcpClient.InitThread;var I: Integer; AThreadType: TTcpThreadType;begin FSendDataList := TThreadList.Create; FRecvDataList := TThreadList.Create; FCahceDataList := TThreadList.Create; for AThreadType := Low(TTcpThreadType) to High(TTcpThreadType) do begin FTcpThread[AThreadType] := TCPTcpThread.Create(True); FTcpThread[AThreadType].FreeOnTerminate := False; case AThreadType of tt_Send: FTcpThread[AThreadType].OnExecuteProc := ExcuteSendProc; tt_Recv: FTcpThread[AThreadType].OnExecuteProc := ExcuteRecvProc; tt_Handle: FTcpThread[AThreadType].OnExecuteProc := ExcuteHandleProc; end; FTcpThread[AThreadType].Start; end;end;procedure TCPTcpClient.FreeThread;var I: Integer; AThreadType: TTcpThreadType;begin for AThreadType := Low(TTcpThreadType) to High(TTcpThreadType) do begin if FTcpThread[AThreadType].Suspended then{$WARN SYMBOL_DEPRECATED OFF} FTcpThread[AThreadType].Resume;{$WARN SYMBOL_DEPRECATED ON} FTcpThread[AThreadType].Terminate; FTcpThread[AThreadType].WaitFor; FTcpThread[AThreadType].Free; FTcpThread[AThreadType] := nil; end; ClearData; FSendDataList.Free; FRecvDataList.Free; FCahceDataList.Free;end;procedure TCPTcpClient.InitHostAddr(const AHost: string; const APort: Integer);begin FHost := AHost; FPort := APort;end;function TCPTcpClient.Send(const AData: Pointer; const ASize: NativeInt): Boolean;begin Result := PushToSendCahce(AData, ASize);end;function TCPTcpClient.TryConnect: Boolean;begin try FTCPClient.Host := FHost; FTCPClient.Port := FPort; FTCPClient.Connect; FConnected := True; except on E: Exception do begin FConnected := False; end; end; Result := FConnected;end;{ TCPTcpClient.TCPTcpThread }procedure TCPTcpClient.TCPTcpThread.Execute;begin inherited; while not Terminated do begin if Assigned(FOnExecuteProc) then FOnExecuteProc; end;end;end.
相关阅读 >>
Delphi 新增功能之: ioutils 单元(7): tfile 结构的功能
Delphi d10.x 并行库ppl编程之 tparallel.for
Delphi fdconnection1获取查询语句的第一个值
Delphi datetimetogmt gmt时间与tdatetime转换
Delphi winapi: getclassname - 获取指定窗口的类名
更多相关阅读请进入《Delphi》频道 >>