我正在搞乱Delphi 2009提供的Indy 10,并且在OnExecute触发时无法从IOHandler获取所有数据……
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext); var RxBufStr: UTF8String; RxBufSize: Integer; begin if AContext.Connection.IOHandler.Readable then begin RxBufSize := AContext.Connection.IOHandler.InputBuffer.Size; if RxBufSize > 0 then begin SetLength(RxBufStr,RxBufSize); AContext.Connection.IOHandler.ReadBytes(TBytes(RxBufStr),RxBufSize,False); end; end; end;
AContext.Connection.IOHandler.InputBuffer.Size似乎不可靠并经常返回0,但是在下次运行时,OnExecute它将获取正确的字节数,但为时已晚.
基本上我希望能够只获取所有数据,将其填充到UTF8String(不是Unicode字符串),然后解析一个特殊的标记.所以我没有标题,消息长度可变.似乎Indy 10 IOHandlers没有为此设置,或者我只是错误地使用它.
做一些像传递一定大小的缓冲区,尽可能多地填充它并返回实际填充的字节数然后继续运行(如果还有更多)会很好.
除了TIdSchedulerOfFiber的状态之外,这看起来非常有趣,它有用吗?有人用吗?我注意到它不在Delphi 2009的标准安装中.
更新:我发现Msg:= AContext.Connection.IOHandler.ReadLn(#0,enUTF8);哪个有效,但我仍然想知道上述问题的答案,是因为它是基于阻止IO吗?这使得TIdSchedulerOfFiber更加热衷于此.
解决方法
你不应该像这样使用Readable().请尝试以下方法:
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext); var RxBuf: TIdBytes; begin RxBuf := nil; with AContext.Connection.IOHandler do begin CheckForDataOnSource(10); if not InputBufferIsEmpty then begin InputBuffer.ExtractToBytes(RxBuf); // process RxBuf as needed... end; end; end;
或者:
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext); var RxBufStr: String; // not UTF8String begin with AContext.Connection.IOHandler do begin CheckForDataOnSource(10); if not InputBufferIsEmpty then begin RxBufStr := InputBuffer.Extract(-1,enUtf8); // Alternatively to above,you can set the // InputBuffer.Encoding property to enUtf8 // beforehand,and then call TIdBuffer.Extract() // without any parameters. // // Or,set the IOHandler.DefStringEncoding // property to enUtf8 beforehand,and then // call TIdioHandler.InputBufferAsString() // process RxBufStr as needed... end; end; end;
至于TIdSchedulerOfFiber – 此时SuperCore包实际上已经死了.它还没有在很长一段时间内完成,也没有与最新的Indy 10架构保持同步.我们可能会在以后尝试复活它,但它不在我们不久的将来的计划中.