Delphi IOHandler读取未知字节数

Delphi IOHandler读取未知字节数,delphi,Delphi,我是DelphiXe5新手,主要使用VB.Net和一些Java。我试图从传入的TCP连接中读取未知数量的字节,但在研究如何确定要读取的输入缓冲区中有多少字节时却没有任何运气。似乎我尝试的每一种方法,即ReadBytes、ReadStream等,都需要我明确地告诉他们要读取多少字节,或者他们阻塞了多少字节。我只需要一种方法来确定输入缓冲区中有多少字节,这样我就可以使用ReadBytes来读取它们 begin Client.IOHandler.CheckForDataOnSource(300);

我是DelphiXe5新手,主要使用VB.Net和一些Java。我试图从传入的TCP连接中读取未知数量的字节,但在研究如何确定要读取的输入缓冲区中有多少字节时却没有任何运气。似乎我尝试的每一种方法,即ReadBytes、ReadStream等,都需要我明确地告诉他们要读取多少字节,或者他们阻塞了多少字节。我只需要一种方法来确定输入缓冲区中有多少字节,这样我就可以使用ReadBytes来读取它们

begin
  Client.IOHandler.CheckForDataOnSource(300);
  if Not Client.IOHandler.InputBufferIsEmpty then
    Client.IOHandler.ReadBytes(rxBuf);
end;
为了避免阻塞,我需要提供输入缓冲区中的字节数,但我无法确定如何做到这一点。我尝试了InputBuffer.Size,但它返回的数字比可能的要大得多

我现在尝试了以下方法:

begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    if Not Client.IOHandler.InputBufferIsEmpty then
    begin
      Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
    end;
  end
  else
    Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
end;
当我放置一个断点并单步执行代码时,代码跳过ExtractToBytes,即使输入缓冲区中有数据,rxBuf仍然为零。为什么?

我以前遗漏了一些代码。事情是这样的

while stop-start <MainForm.Timeout do
begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    stop := Ticks;
    if Not Client.IOHandler.InputBufferIsEmpty then
    begin
      Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
      break;
    end;
  end
  else
    Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
  break;
end;

同时停止启动
InputBuffer.Size
InputBuffer
内存中实际的字节数。它不能大于实际存储的值
InputBufferIsEmpty()
只返回
InputBuffer.Size>0
与否

begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    Client.IOHandler.CheckForDisconnect;
    if Client.IOHandler.InputBufferIsEmpty then Exit;
  end;
  Client.IOHandler.ReadBytes(rxBuf, Client.IOHandler.InputBuffer.Size);
end;
或者,无条件地使用
InputBuffer.ExtractToBytes()
提取
InputBuffer
中当前存在的内容,即使它恰好为空:

begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    Client.IOHandler.CheckForDisconnect;
    if Client.IOHandler.InputBufferIsEmpty then Exit;
  end;
  Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
end;
或者,您可以将
-1
传递给
ReadBytes()
,这告诉它返回
InputBuffer
中当前存在的任何内容(它将首先调用
IOHandler.ReadFromSource()
填充
InputBuffer
,然后从中提取):

更新:无论是否读取任何内容,您的循环都在调用
break
。这就是你真正想要的吗?如果没有,则需要将最后一个
中断
移动到
开始/结束
块中,以便仅在调用
提取字节()
时对其进行计算:

while GetTickDiff(start, Ticks) < MainForm.Timeout do
begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    if Not Client.IOHandler.InputBufferIsEmpty then
    begin
      Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
      break;
    end;
  end
  else
  begin
    Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
    break;
  end;
end;
在这种情况下,您可以完全摆脱循环,只利用Indy自己的超时:

Client.IOHandler.CheckForDataOnSource(MainForm.Timeout);
Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
或:


InputBuffer.Size
InputBuffer
内存中实际的字节数。它不能大于实际存储的值
InputBufferIsEmpty()
只返回
InputBuffer.Size>0
与否

begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    Client.IOHandler.CheckForDisconnect;
    if Client.IOHandler.InputBufferIsEmpty then Exit;
  end;
  Client.IOHandler.ReadBytes(rxBuf, Client.IOHandler.InputBuffer.Size);
end;
或者,无条件地使用
InputBuffer.ExtractToBytes()
提取
InputBuffer
中当前存在的内容,即使它恰好为空:

begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    Client.IOHandler.CheckForDisconnect;
    if Client.IOHandler.InputBufferIsEmpty then Exit;
  end;
  Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
end;
或者,您可以将
-1
传递给
ReadBytes()
,这告诉它返回
InputBuffer
中当前存在的任何内容(它将首先调用
IOHandler.ReadFromSource()
填充
InputBuffer
,然后从中提取):

更新:无论是否读取任何内容,您的循环都在调用
break
。这就是你真正想要的吗?如果没有,则需要将最后一个
中断
移动到
开始/结束
块中,以便仅在调用
提取字节()
时对其进行计算:

while GetTickDiff(start, Ticks) < MainForm.Timeout do
begin
  if Client.IOHandler.InputBufferIsEmpty then
  begin
    Client.IOHandler.CheckForDataOnSource(1000);
    if Not Client.IOHandler.InputBufferIsEmpty then
    begin
      Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
      break;
    end;
  end
  else
  begin
    Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
    break;
  end;
end;
在这种情况下,您可以完全摆脱循环,只利用Indy自己的超时:

Client.IOHandler.CheckForDataOnSource(MainForm.Timeout);
Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
或:


多谢各位。我不明白的是,如果输入缓冲区中有数据,ExtractBytes为什么不会被计算?这是我试图实现的逻辑。我正在通过TCP与串行设备通信。我给它发送了一个打开通信的字符,它用一些大小不同的信息进行响应

// Stay in loop until a certain amount of time has passed with no data
// I understand I can use the timeout as well
while GetTickDiff(start, Ticks) < MainForm.Timeout do
  begin
    if Client.IOHandler.InputBufferIsEmpty then
      begin
        Client.IOHandler.CheckForDataOnSource(1000);
        if Not Client.IOHandler.InputBufferIsEmpty then
          begin
            // If there is data in the buffer get it
            // But why is ExtractToBytes not evaluated
            Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
            // I break the loop because I am assuming ExtractToBytes has been evaluated
            break;
          end;
      end
    else
      begin
      Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
      break;
  end;
//在没有数据的情况下,在一定时间内保持循环
//我知道我也可以使用超时
而GetTickDiff(start,Ticks)
结束


我显然误解的是,仅仅因为输入缓冲区中有数据,ExtractToBytes不一定会被计算。谢谢你的输入,我会再多玩一玩。

谢谢。我不明白的是,如果输入缓冲区中有数据,ExtractBytes为什么不会被计算?这是我试图实现的逻辑。我正在通过TCP与串行设备通信。我给它发送了一个打开通信的字符,它用一些大小不同的信息进行响应

// Stay in loop until a certain amount of time has passed with no data
// I understand I can use the timeout as well
while GetTickDiff(start, Ticks) < MainForm.Timeout do
  begin
    if Client.IOHandler.InputBufferIsEmpty then
      begin
        Client.IOHandler.CheckForDataOnSource(1000);
        if Not Client.IOHandler.InputBufferIsEmpty then
          begin
            // If there is data in the buffer get it
            // But why is ExtractToBytes not evaluated
            Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
            // I break the loop because I am assuming ExtractToBytes has been evaluated
            break;
          end;
      end
    else
      begin
      Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf);
      break;
  end;
//在没有数据的情况下,在一定时间内保持循环
//我知道我也可以使用超时
而GetTickDiff(start,Ticks)
结束

我显然误解的是,仅仅因为输入缓冲区中有数据,提取到字节w