C++ 将结构序列化为char*并通过UDP发送

C++ 将结构序列化为char*并通过UDP发送,c++,sockets,C++,Sockets,我正在使用sendto(..)和recvfrom()通过UDP套接字与运行相同程序的其他服务器(相同或类似系统)交换一个名为struct update_packet的结构 根据stackoverflow.com/questions/27055729/的答案,我编写了一个函数来序列化struct update\u数据包 struct update_packet { uint16_t num_update_fields; uint16_t port; uint32_t IP;

我正在使用sendto(..)和recvfrom()通过UDP套接字与运行相同程序的其他服务器(相同或类似系统)交换一个名为
struct update_packet
的结构

根据stackoverflow.com/questions/27055729/的答案,我编写了一个函数来序列化
struct update\u数据包

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();
    }
                       ...
};
然后将其实例化为

struct update_packet up;
const char * up_to_send = up.serialize();
并发送

我把一些
cout
放在
serialize()
中进行测试

我明白了

    8
str.data()
为空字符串,大小为8

此外,当我通过UDP套接字接收数据并从
recvfrom
打印返回值(即接收到的字节)时,它打印0,并且接收到的消息与外观怪异的字符相同,但只有一个字符

问题出在哪里?我如何解决这个问题,以便在接收端接收和检索数据?

中,您将原始二进制数据写入
ostringstream
(一个字符串),而不实际将其转换为字符串。如果要写入原始二进制数据,需要写入基本的
ostream

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]);
        }
    }
}
此外,由于您实际上没有将其转换为字符串,因此无法将其打印出来,就像它是一个字符串一样


如果您坚持使用
ostringstream
,则项目规范要求使用
oss.put()
oss.write()
插入原始二进制文件,而不是使用
operator或big Endianness。如果使用little-Endian,我如何用Big-Endian写入
ostringstream
,并在接收端读取它?@user241822如果将其转换为数字的字符串表示形式,则将“去掉”Endian。Endianness是数字在内存中二进制表示的固有特性。如果您想发送原始二进制数据,那么应该以“网络字节顺序”发送,即big-endian。有一组C库函数可以将数字从主机字节顺序转换为网络字节顺序,然后再转换回来:
htonl()
ntohl()
用于
long
s,还有一些用于
short
s。原始二进制和字符串表示法都有优点和缺点。。。
cout << str.data() << "\t" << sizeof(str.data()) << endl;
    8