Indy,如何知道所需缓冲区的大小?
Posted
技术标签:
【中文标题】Indy,如何知道所需缓冲区的大小?【英文标题】:Indy, How to know size of buffer needed? 【发布时间】:2011-07-08 13:24:20 【问题描述】:我在使用 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 进行通信的协议是什么?当提出这样的位级问题时,这是一个非常重要的问题。 【参考方案1】:简单的答案是:你不能。 TCP 是一个stream 协议,所以没有message 的概念。数据以块的形式接收,其大小可能(并且将)与实际发送的缓冲区不同(网络堆栈可以随意切片或合并流)。 您可以在 TCP 之上构建消息协议,例如通过“大小字段”开始传输以及随后的每个消息,然后仅等待所需的字节;您仍然需要检查收到的实际尺寸,并在适用的情况下重新阅读其余尺寸。
重点是:数据包长度在 TCP 世界中与发送消息的长度无关。 TIdTCPConnection
在所有 Read
方法背后所做的是:
从网络堆栈中读取所有个可用数据,将其附加到内部输入缓冲区中,如果可用,则从缓冲区的开头返回请求的N个字节(等待下一个块,如果没有)。
【讨论】:
如果我使用 AThread.connection.ReadStream 会怎样?我会添加更多描述【参考方案2】:您显示的数据中的第 3 和第 4 个字节指定了正在发送的数据的总大小。您接近尝试ReadInteger()
,但您使用它的方式包括第一个和第二个字节,这是错误的。试试这个:
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;
【讨论】:
你能解释一下这行“DataSize := AThread.Connection.ReadSmallInt - 4;” 第 3 和第 4 个字节由一个 16 位网络字节序整数组成,该整数指定数据包的总大小。该长度包括前 4 个字节。因此,您必须检索长度,然后减去 4 以获得剩余有效负载的长度。以上是关于Indy,如何知道所需缓冲区的大小?的主要内容,如果未能解决你的问题,请参考以下文章