当前位置 : 主页 > 编程语言 > delphi >

delphi – Indy,如何知道所需缓冲区的大小?

来源:互联网 收集:自由互联 发布时间:2021-06-23
我在使用Indy(idTCPServer组件)读取客户端发送的数据时遇到了一些问题,数据本身是十六进制格式化的,所以我不能使用AThread.Connection.ReadLn();为了那个原因… 这里我的样本数据由客户发送
我在使用Indy(idTCPServer组件)读取客户端发送的数据时遇到了一些问题,数据本身是十六进制格式化的,所以我不能使用AThread.Connection.ReadLn();为了那个原因…

这里我的样本数据由客户发送

24 24 00 11 12 34 56 FF FF FF FF 50 00 8B 9B 0D 0A

要么

24 24 00 13 12 34 56 FF FF FF FF 90 02 00 0A 8F D4 0D 0A

PS:它是以十六进制为单位的字节数据(数据长度可能因命令而异,最多160字节),我无法获得字符串表示,因为$00被翻译为null(这意味着我不能使用ReadLn)

这是我的示例代码

procedure TfrmMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
  Msg : Array[0..255] of Byte;
begin      
  AThread.connection.ReadBuffer(Msg,SizeOf(Msg));
  AThread.connection.WriteBuffer(Msg,MsgSize,true);
end;

如果客户端不发送255字节数据,此代码将无法工作,而在我的情况下数据长度可以变化,我试过这个,但没有输出响应

procedure TfrmMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
  Msg : Array of Byte;
  MsgSize : integer;
begin  
  MsgSize := AThread.connection.ReadInteger; //doesn't actually get packet length?
  SetLength(Msg, MsgSize);    
  AThread.connection.ReadBuffer(Msg,MsgSize);
  AThread.connection.WriteBuffer(Msg,MsgSize,true);
end;

那么我究竟能算出客户端发送的字节数据(包长度)究竟是多少?或者有人能告诉我正确的代码来读取数据吗?

简单的答案是:你做不到. TCP是一种流协议,因此没有消息的概念.数据以块的形式接收,块的大小可能(并且将)与实际发送的缓冲区不同(网络堆栈可以随意切片或合并流).
您可以在TCP之上构建消息协议,例如通过“大小字段”开始传输和每个后续消息,然后只等待所需的字节;您仍然需要检查收到的实际尺寸并重新阅读其余部分(如果适用).

重点是:TCP世界中的数据包长度与发送消息的长度无关.TIdTCPConnection在所有Read方法背后的作用是:从网络堆栈读取所有可用数据,将其附加到内部输入缓冲区并从缓冲区的开头返回请求的N个字节(如果可用)(如果没有,则等待下一个块).

网友评论