gpt4 book ai didi

c++ - 如何正确转换也是不同数据类型的各种(已知)长度数据包的流?

转载 作者:可可西里 更新时间:2023-11-01 02:50:04 27 4
gpt4 key购买 nike

问题:

我正在编写一个 C++ 程序,我想在其中从 TCP/IP 套接字读取数据流。数据由几个不同长度和数据类型的数据包组成,但是,它们都是以十六进制格式接收的。在此图中可以看到数据包的长度及其数据类型: table .我想将接收到的十六进制格式数据转换回数据包各自的原始数据类型。

背景和我的尝试:

我在 Python 中找到了一种相当简单的方法:
- 根据已知长度接收每个数据包
- 将它们编码为十六进制
- 根据数据类型解压它们

这是一个示例:

import socket
import struct
HOST = "192.168.0.25" # The remote host
PORT_30003 = 30003

while (True):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT_30003))
print ""
packet_1 = s.recv(4)
packet_2 = s.recv(8)
packet_3 = s.recv(48)
packet_4 = s.recv(48)
packet_5 = s.recv(48)
packet_6 = s.recv(48)
packet_7 = s.recv(48)
packet_8 = s.recv(48)
packet_9 = s.recv(48)
packet_10 = s.recv(48)
packet_11 = s.recv(48)

packet_1 = packet_1.encode("hex")
messageSize = struct.unpack('!i', packet_1.decode('hex'))[0]
print "messageSize = ", messageSize

packet_2 = packet_2.encode("hex")
Time = struct.unpack('!d', packet_2.decode('hex'))[0]
print "Time = ", Time

我不太关心接下来的这些数据包,所以我会跳到相关的数据包(从 packet_12 开始)。我要把每个 48 字节的数据包拆分成更小的 8 字节大小的数据包,因为 48 字节实际上是 6 个独立的值,如上图所示...

 packet_12x = s.recv(8)
packet_12x = packet_12x.encode("hex")
x = struct.unpack('!d', packet_12x.decode('hex'))[0]
print "X = ", x * 1000

packet_12y = s.recv(8)
packet_12y = packet_12y.encode("hex")
y = struct.unpack('!d', packet_12y.decode('hex'))[0]
print "Y = ", y * 1000

# And so on.....

这会产生消息长度(应始终为 1108)、服务器时间和机器人工具的 X、Y 位置。


C++ 尝试:

在 C++ 中尝试此操作时,我对数据类型、字节顺序等感到有点困惑。我设法正确生成了第一个数据包(如我所料打印 1108)。但是,下一个数据包与 Python 实现的输出不匹配。这是我拥有的:

connectTcpClient("192.168.0.25");

// This works as expected
int buffer1;
recv(sock, &buffer1, 4, 0);
buffer1 = ntohl(buffer1);

// Prints "messageSize = 1108"
std::cout << "messageSize = " << buffer1 << std::endl;

// This does not produce the same result as the Python code
// When trying with a unsigned long long int instead of double
double buffer2;
recv(sock, &buffer2, 8, 0);
buffer2 = ntohl(buffer2);

// This prints "Time: 0"
std::cout << "Time: " << buffer2 << std::endl;

如果我改为尝试声明我的 buffer2:unsigned long long int buffer2
我得到了更接近我想要的东西,但它当然不像我期望的那样是双倍的。将 buffer2 转换为 double 只会导致 0。

预期结果

我希望时间类似于 1379408.432,而不是整数。来自 packet_12 的 X、Y 和 Z 坐标也应该是 double 值。

最佳答案

ntohl 函数需要一个 32 位整数并更改值以便有效地交换字节,假设主机字节顺序是小端。它不适用于 double 类型的值。

您需要将值读入大小为 8 的 char 数组,反转字节,然后使用 memcpy 将字节复制到 double.

int i;
unsigned char dbuff[sizeof(double)];
recv(sock, dbuff, sizeof(dbuff), 0);

if (ntohl(0x12345678) == 0x78563412) {
for (i=0; i<sizeof(double)/2; i++) {
unsigned char tmp = dbuff[i];
dbuff[i] = dbuff[sizeof(double)-1-i];
dbuff[sizeof(double)-1-i] = tmp;
}
}

double val;
memcpy(&val, dbuff, sizeof(double));

请注意,这取决于发送方和接收方对 double 具有相同的表示。

关于c++ - 如何正确转换也是不同数据类型的各种(已知)长度数据包的流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55497366/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com