7

我正在搞乱 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 更加热衷。

4

2 回答 2

17

你不应该那样使用 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 架构保持同步。我们可能会在以后尝试复活它,但这不在我们近期的计划中。

于 2009-02-13T02:07:31.533 回答
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; 
于 2011-05-11T11:32:52.907 回答