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

标签 c++ sockets

我正在使用 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/

相关文章:

python - 我无法理解 python 中的轮询/选择

c++ - 使用模板指定成员变量

c++ - Ubuntu 或 Windows 中的代码块。有什么不同吗?

c++ - 为什么 istream_iterator<string>(ifstream ("test.txt")) 会导致错误?

java - java Socket编程中从服务器发送文件列表到客户端 - PrintWriter无法发送?

c - C 的非 POSIX 套接字

c++ - 十六进制转义序列的最大长度

c++ - C++中的插入排序实现导致多个错误

c - sendto 需要很多时间

c - 套接字编程-更改套接字IP