我正在使用随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更加热衷。
答案 0 :(得分:16)
你不应该像这样使用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架构保持同步。我们可能会在以后尝试复活它,但它不在我们不久的将来的计划中。
答案 1 :(得分:1)
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
RxBufStr: UTF8String;
RxBufSize: Integer;
begin
if AContext.Connection.IOHandler.Readable then
begin
AContext.Connection.IOHandler.ReadBytes(TBytes(RxBufStr),-1, False);
end;
end;