当前位置:  开发笔记 > 编程语言 > 正文

Delphi 2009,Indy 10,TIdTCPServer.OnExecute,如何获取InputBuffer中的所有字节

如何解决《Delphi2009,Indy10,TIdTCPServer.OnExecute,如何获取InputBuffer中的所有字节》经验,为你挑选了1个好方法。

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



1> Remy Lebeau..:

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


是的,OnExecute事件由TIdTCPServer按设计自动循环.CheckForDataOnSource()的timeout参数有助于防止调用线程在没有数据可用的空闲时段内占用所有CPU周期.
CheckForDataOnSource()不会查看InputBuffer是否已包含数据.它直接进入套接字.如果返回False,则套接字中没有待处理数据.
使用CheckForDataOnSource()的最佳方法是仅在InputBuffer为空时调用它,而不是在每个循环迭代器上无条件地调用它.
@BenjaminWeiss:RxBuf是一个编译器管理的动态数组,当它超出范围时会自动释放.
推荐阅读
ar_wen2402851455
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有