简体   繁体   English

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

[英]Delphi 2009, Indy 10, TIdTCPServer.OnExecute, how to grab all the bytes in the InputBuffer

I am messing around with the Indy 10 supplied with Delphi 2009 and am having trouble with getting all the data from the IOHandler when OnExecute fires... 我正在搞乱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 doesn't seem reliable and often returns 0, but on the next run throug the OnExecute it'll pick up the right number of bytes, but that is too late. AContext.Connection.IOHandler.InputBuffer.Size似乎不可靠并经常返回0,但是在下一次运行时,OnExecute它将获取正确的字节数,但为时已晚。

Essentially I want to be able to just grab all the data, stuff it into a UTF8String ( not a Unicode string) and then parse for a special marker. 基本上我希望能够只获取所有数据,将其填充到UTF8String( 不是 Unicode字符串),然后解析一个特殊的标记。 So I have no headers and messages are variable length. 所以我没有标题,消息长度可变。 It seems the Indy 10 IOHandlers are not setup for this or I am just using it wrong. 似乎Indy 10 IOHandlers没有为此设置,或者我只是错误地使用它。

It would be nice to do something like pass a buffer of a certain size, fill it as much as possible and return the number of bytes actually filled and then keep going if there are more. 做一些像传递一定大小的缓冲区,尽可能多地填充它并返回实际填充的字节数然后继续运行(如果还有更多)会很好。

As an aside what's the status of TIdSchedulerOfFiber, this looks very interesting, does it work? 除了TIdSchedulerOfFiber的状态之外,这看起来非常有趣,它有用吗? Is anyone using it? 有人用吗? I notice that it isn't in the standard install of Delphi 2009 though. 我注意到它不在Delphi 2009的标准安装中。

Update: I found Msg := AContext.Connection.IOHandler.ReadLn(#0, enUTF8); 更新:我发现Msg:= AContext.Connection.IOHandler.ReadLn(#0,enUTF8); which works but I still would like to know the answer to the above question, is it because it is based on blocking IO? 哪个有效,但我仍然想知道上述问题的答案,是因为它是基于阻止IO吗? Which makes even more keen on this TIdSchedulerOfFiber. 这使得TIdSchedulerOfFiber更加热衷于此。

You should not be using Readable() like that. 你不应该像那样使用Readable()。 Try the following instead: 请尝试以下方法:

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;

Alternatively: 或者:

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;

As for TIdSchedulerOfFiber - the SuperCore package is effectively dead at this time. 至于TIdSchedulerOfFiber - 此时SuperCore包实际上已经死了。 It has not been worked on in a very long time, and is not up-to-date with the latest Indy 10 architecture. 它在很长一段时间内都没有开始工作,并且不与最新的Indy 10架构保持同步。 We may try to resurrect it at a later date, but it is not in our plans for the near future. 我们可能会在以后尝试复活它,但它不在我们不久的将来的计划中。

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; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM