我在使用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 是一个流协议(protocol),因此没有消息的概念。数据以 block 的形式接收,其大小可能(并且将会)与实际发送的缓冲区不同(网络堆栈可以随意切片或合并流)。
您可以在 TCP 之上构建消息协议(protocol),例如通过“大小字段”开始传输以及每个后续消息,然后仅等待所需的字节;您仍然需要检查收到的实际尺寸并重新阅读其余部分(如果适用)。
要点是:TCP 世界中的数据包长度与发送消息的长度无关。
TIdTCPConnection
在所有 Read
方法背后所做的是:
从网络堆栈读取所有可用数据,将其附加到内部输入缓冲区,并从缓冲区开头返回请求的N个字节(如果可用)(等待下一个 block ) ,如果没有)。
关于delphi - Indy,如何知道所需缓冲区的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5189618/