Indy,如何知道所需缓冲区的大小?
我在使用 Indy (idTCPServer 组件)读取客户端发送的数据时遇到一些问题,数据本身是十六进制格式,所以我无法使用 AThread.Connection.ReadLn();< /strong> 为此...
PS发送的示例数据
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
:它以十六进制字节为单位(数据长度可能因命令而异,最大 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;
,那么我如何准确计算客户端发送的字节数据(数据包长度)?或者有人可以告诉我读取数据的正确代码吗?
I have some problem when using Indy (idTCPServer component) to read data send by client, the data itself was a hex formatted so i can't use AThread.Connection.ReadLn(); for that...
Here my sample data sended by client
24 24 00 11 12 34 56 FF FF FF FF 50 00 8B 9B 0D 0A
or
24 24 00 13 12 34 56 FF FF FF FF 90 02 00 0A 8F D4 0D 0A
PS: it's in bytes hexadecimal (data length may vary depend on command, at maximum 160 bytes) which i can't get string representation since $00 translated to null (which mean i can't use ReadLn)
Here my sample code
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;
this code will not work if client not send 255 byte data, while in my case data length can be vary, i have tried this, but no response outputted
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;
so how exactly i can count how many byte data sended by client (packet length)? or could someone tell me the right code to read the data?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
简单的答案是:你不能。 TCP 是一个流协议,因此没有消息的概念。数据以块的形式接收,其大小可能(并且将会)与实际发送的缓冲区不同(网络堆栈可以随意切片或合并流)。
您可以在 TCP 之上构建消息协议,例如通过“大小字段”启动传输以及每个后续消息,然后仅等待所需的字节;您仍然需要检查收到的实际尺寸并重新阅读其余部分(如果适用)。
要点是:TCP 世界中的数据包长度与发送消息的长度无关。
TIdTCPConnection
在所有Read
方法背后所做的事情是:从网络堆栈读取所有可用数据,将其附加到内部输入缓冲区,并从缓冲区开头返回请求的N个字节(如果可用)(等待下一个块) , 如果不)。
The simple answer is: you can't. TCP is a stream protocol, so there is no concept of a message. The data is received in chunks, whose sizes may (and will) differ from the actually sent buffers (the network stack is free to slice or merge the stream at will).
You may built a message protocol on top of TCP, e.g. by starting the transmission, and every consequent message, by a "size field" and then waiting only for the bytes needed; you still need to check the actual size received and re-reading the rest if applicable.
The point is: packet length in the TCP world has nothing to do with the length of the sent messages.
What
TIdTCPConnection
does behind all theRead
-methods is:reading all available data from the network stack, appending it into an internal input buffer and returning the requested N bytes from the beginning of the buffer, if available (waiting for next chunk, if not).
您显示的数据中的第三个和第四个字节指定了正在发送的数据的总大小。您很接近尝试
ReadInteger()
,但您使用它的方式包括第一个和第二个字节,这是错误的。试试这个:The 3rd and 4th bytes in the data you have shown specify the total size of the data being sent. You were close to try
ReadInteger()
, but the way you used it includes the 1st and 2nd bytes, which is wrong. Try this instead: