我正在使用 sendto(..) 和 recvfrom() 通过 UDP 套接字与运行相同程序的其他服务器(相同或相似系统)交换名为 struct update_packet
的结构。
根据 stackoverflow.com/questions/27055729/的回答,我编写了一个函数来序列化 struct update_packet
struct update_packet {
uint16_t num_update_fields;
uint16_t port;
uint32_t IP;
vector<struct node> nodes;
const char * serialize() const {
ostringstream oss;
put_u16_as_big(oss, num_update_fields);
put_u16_as_big(oss, port);
put_u32_as_big(oss, IP);
for(size_t i = 0; i < num_update_fields; ++i) {
put_u32_as_big(oss, nodes[i].IP);
put_u16_as_big(oss, nodes[i].port);
put_u16_as_big(oss, nodes[i].nil);
put_u16_as_big(oss, nodes[i].server_id);
put_u16_as_big(oss, nodes[i].cost);
}
string str = oss.str();
cout << str << "\t" << str.size() << endl;
cout << str.data() << "\t" << sizeof(str.data()) << endl;
return str.data();
}
...
};
和 put_u16_as_big
是一个辅助函数,它将 Big Endian 中的 uint16_t
放入引用的 ostringstream
。
void put_u16_as_big(ostringstream& oss, uint16_t data) {
if (is_big_endian()) {
oss.write((const char *)&data, sizeof(data));
}
else {
const char * ptr = (const char *)&data;
unsigned int s = sizeof(data);
for(unsigned int i=0; i < s; ++i) {
oss.put(ptr[s-1-i]);
}
}
}
然后像这样实例化
struct update_packet up;
const char * up_to_send = up.serialize();
并发送。
我在 serialize()
中放了一些 cout
用于测试。
与
cout << str << "\t" << str.size() << endl;
它打印看起来很奇怪的字符(框中的数字),大小为 44。
但是,使用 str.data()
返回 const char *
cout << str.data() << "\t" << sizeof(str.data()) << endl;
我明白了
8
str.data()
为空字符串,大小为 8
此外,当我通过 UDP 套接字接收数据并打印 recvfrom
的返回值(即接收到的字节)时,它打印 0,并且接收到的消息与那个看起来很奇怪的字符相同, 但只有一个字符。
问题是什么,我该如何解决才能在接收端接收和检索数据?
最佳答案
在put_u16_as_big()
,您正在将原始二进制数据写入 ostringstream
(一个字符串)而不实际将其转换为字符串。如果你想写原始二进制数据,你需要写一个基本的 ostream
.
此外,由于您实际上并未将其转换为字符串,因此您无法将其打印出来,就好像它是一个字符串一样。
如果你坚持使用ostringstream
然后而不是使用 oss.put()
和 oss.write()
这将插入你应该使用的原始二进制文件 operator<<
这将插入格式化输出。当然,如果您真的使用字符串,那么字节顺序就无关紧要了。
关于c++ - 将结构序列化为 char * 并通过 UDP 发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27071683/