2014-02-21 36 views
2

我是Delphi XE5的新手,主要与VB.Net和一些Java一起工作。我试图从传入的TCP连接中读取未知数量的字节,并且没有任何运气研究如何确定要读取的输入缓冲区中有多少个字节。看来,我尝试的每种方法,即ReadBytes,ReadStream等都要求我明确告诉他们要读取多少个字节或它们是否被阻塞。我只需要一种方法来确定输入缓冲区中有多少个字节,以便我可以使用ReadBytes来读取它们。Delphi IOHandler读取未知的字节数

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; 

我知道缓冲区中存在数据,因为通过代码进入break;但ExtractToBytes(rxBuf)未被评估,并且不知道为什么。

回答

3

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; 

或者,您也可以通过-1ReadBytes(),告诉它返回无论目前在InputBuffer(它将首先呼叫IOHandler.ReadFromSource()填充InputBuffer,然后再提取之前):

begin 
    Client.IOHandler.ReadBytes(rxBuf, -1, False); 
end; 

更新:无论是否读取任何内容,您的循环呼叫break。这是你真正想要的吗?如果没有,那么你需要最后break移动到begin/end块,使得它仅被评估,如果ExtractToBytes()被称为:

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; 

在这种情况下,你就可以简化循环了一下:

start := Ticks; 
while Client.IOHandler.InputBufferIsEmpty do 
begin 
    if GetTickDiff(start, Ticks) >= MainForm.Timeout then Break; 
    Client.IOHandler.CheckForDataOnSource(1000); 
end; 
Client.IOHandler.InputBuffer.ExtractToBytes(rxBuf); 

在这种情况下,你可以只得到完全摆脱循环的,只是利用印自己的超时代替:

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

或者:

Client.IOHandler.ReadTimeout := MainForm.Timeout; 
Client.IOHandler.ReadBytes(rxBuf, -1, False); 
+0

请参阅我上面的修改。感谢您的评论。 – user1549123

0

谢谢。我不明白的是,为什么如果输入缓冲区中有数据不会评估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; 

end;

我明显误解的是,仅仅因为输入缓冲区中有数据,ExtractToBytes不一定会被评估。感谢您的意见,我会多花一点时间。