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

发布于 2024-10-20 03:23:32 字数 1227 浏览 8 评论 0原文

我在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

赠佳期 2024-10-27 03:23:32

简单的答案是:你不能。 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 the Read-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).

零崎曲识 2024-10-27 03:23:32

您显示的数据中的第三个和第四个字节指定了正在发送的数据的总大小。您很接近尝试 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;

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:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文