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

Delphi Indy,如何知道所需缓冲区的大小?,delphi,buffer,indy,Delphi,Buffer,Indy,我在使用Indy(idTCPServer组件)读取客户端发送的数据时遇到一些问题,数据本身是十六进制格式的,因此我无法使用AThread.Connection.ReadLn()为此 这里是我的客户发送的示例数据 24 24 00 11 12 34 56 FF FF FF FF 50 00 8B 9B 0D 0A 或 PS:以十六进制字节表示(数据长度可能因命令而异,最大值为160字节),由于$00转换为null,我无法获取字符串表示形式(这意味着我无法使用ReadLn) 这是我的示例代码 pr

我在使用Indy(idTCPServer组件)读取客户端发送的数据时遇到一些问题,数据本身是十六进制格式的,因此我无法使用AThread.Connection.ReadLn()为此

这里是我的客户发送的示例数据

24 24 00 11 12 34 56 FF FF FF FF 50 00 8B 9B 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字节(如果可用)(如果不可用,则等待下一个块)。

显示的数据中的第3和第4字节指定要发送的数据的总大小。您差点就要尝试
ReadInteger()
,但您使用它的方式包括第1和第2个字节,这是错误的。请尝试以下方法:

procedure TfrmMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
  Unknown: Smallint; // maybe a msg type?
  DataSize: Smallint;
  Data: Array of Byte;
begin
  Unknown := AThread.Connection.ReadSmallInt;
  DataSize := AThread.Connection.ReadSmallInt - 4;
  SetLength(Data, DataSize);
  AThread.Connection.ReadBuffer(Data[0], DataSize);
  //...
end;

如果我使用AThread.connection.ReadStream怎么办?我将添加更多描述为什么使用原始TCP组件?您尝试通过TCP进行通信的协议是什么?当问这样的位级问题时,这是一个非常突出的问题。你能解释一下这行“DataSize:=AThread.Connection.ReadSmallInt-4”吗?第3和第4个字节由一个16位的网络端整数组成,它决定了数据包的总大小。该长度包括前4个字节。所以你必须重新计算长度,然后减去4得到剩余有效载荷的长度。
procedure TfrmMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
  Unknown: Smallint; // maybe a msg type?
  DataSize: Smallint;
  Data: Array of Byte;
begin
  Unknown := AThread.Connection.ReadSmallInt;
  DataSize := AThread.Connection.ReadSmallInt - 4;
  SetLength(Data, DataSize);
  AThread.Connection.ReadBuffer(Data[0], DataSize);
  //...
end;