如何接收一個100字節的字符串使用TIdTcpClient下列條件超時:接收部分數據使用TIdTcpClient
- 如果沒有進來,讀取通話將被阻塞和線程等待永遠
- 如果接收到100個字節,則讀取調用應返回字節字符串
- 如果接收到的字節數超過0字節但小於100,則應在某些超時(例如1秒)後返回Read調用,以便至少返回某些內容一個合理的時間,不會產生超時異常,因爲Delphi IDE的調試模式中的異常處理不是m方便。
我現在不是最佳的代碼如下:
unit Unit2;
interface
uses
System.Classes, IdTCPClient;
type
TTcpReceiver = class(TThread)
private
_tcpc: TIdTCPClient;
_onReceive: TGetStrProc;
_buffer: AnsiString;
procedure _receiveLoop();
procedure _postBuffer;
protected
procedure Execute(); override;
public
constructor Create(); reintroduce;
destructor Destroy(); override;
property OnReceive: TGetStrProc read _onReceive write _onReceive;
end;
implementation
uses
System.SysUtils, Vcl.Dialogs, IdGlobal, IdExceptionCore;
constructor TTcpReceiver.Create();
begin
inherited Create(True);
_buffer := '';
_tcpc := TIdTCPClient.Create(nil);
//_tcpc.Host := '192.168.52.175';
_tcpc.Host := '127.0.0.1';
_tcpc.Port := 1;
_tcpc.ReadTimeout := 1000;
_tcpc.Connect();
Suspended := False;
end;
destructor TTcpReceiver.Destroy();
begin
_tcpc.Disconnect();
FreeAndNil(_tcpc);
inherited;
end;
procedure TTcpReceiver.Execute;
begin
_receiveLoop();
end;
procedure TTcpReceiver._postBuffer();
var buf: string;
begin
if _buffer = '' then Exit;
buf := _buffer;
_buffer := '';
if Assigned(_onReceive) then begin
Synchronize(
procedure()
begin
_onReceive(buf);
end
);
end;
end;
procedure TTcpReceiver._receiveLoop();
var
c: AnsiChar;
begin
while not Terminated do begin
try
c := AnsiChar(_tcpc.IOHandler.ReadByte());
_buffer := _buffer + c;
if Length(_buffer) > 100 then
_postBuffer();
except
//Here I have to ignore EIdReadTimeout in Delphi IDE everywhere, but I want just to ignore them here
on ex: EIdReadTimeout do _postBuffer();
end;
end;
end;
end.
爲什麼不直接使用['IOHandler.ReadBytes()'](http://www.indyproject.org/docsite/html/[email protected]@[email protected])而不是自己努力去做這項艱苦工作? –
@Paul我很確定Indy處理緩衝區比我們大多數人希望能夠管理的更好。如果你只需要50個字節,爲什麼要求100個?在某些時候,你有一個最小的數據包大小,這可能是有用的。等待那個數據包 - 如果它來了,然後處理它,如果它沒有,那麼你無事可做。如果你不關心丟失的數據,或許UDP比TCP更好。 –
@Paul而不是試圖盲目地閱讀,然後處理異常,可能更好的方法是在嘗試讀取之前檢查緩衝區('如果不是IOHandler.InputBufferIsEmpty,則...')。試圖從空的緩衝區讀取沒有意義。更好的是,如果你正在讀取字符串並控制你的命令協議,那麼選擇一個合理的命令終止符,並使用'ReadLn'。 –