gpt4 book ai didi

c++ - 将 int 类型的结构放入 Big Endian 中的 ostream 以转换为 char *

转载 作者:行者123 更新时间:2023-11-28 02:37:08 24 4
gpt4 key购买 nike

我有一条消息要通过 UDP 交换我使用 struct 实现的套接字的 uintN_tstdint.h .

要求传递给 UDP 套接字的任何数据都在 Big Endian 中,当然还有 char * 类型或 const char * .

我运行这个程序的系统是基于 Little Endian 的。

我不熟悉序列化,根据 SO 上的答案,我尝试了 put()将数据倒序排列为 ostringstream去做这个。 (具体见下面代码)

void put_u16_as_big(ostringstream& oss, uint16_t data) {
oss.write((const char *)&data, sizeof(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 的实例时并调用str()方法,数据大小不是应该的(小于8bytes * 2 + 8bytes * 3 *所有服务器的数量,如上表),data()该字符串的方法,它会进一步缩小(到 8)。

最后在对方收到的时候,大小为1。

如何将我的结构序列化为 char *并在不丢失任何数据的情况下发送和接收?

struct包含带 uint16_t 的字段和 uint32_t类型,以及另一个结构的 vector (用于服务器列表),该结构还包含 uint16_t , uint32_tint16_t .

请帮帮我。几天来我一直在努力解决这个问题,但没有运气..

谢谢。

最佳答案

使用套接字 API htons()(主机到网络短)和 htonl()(主机到网络长)函数从本地转换多字节整数机器的本地字节序转换为网络字节顺序(大端)。在大端系统上,该操作是空操作。在小端系统上,字节被交换。您可以使用 ntohs()(网络到主机短)和 ntohl()(网络到主机长)将多字节整数从网络字节顺序转换为本地机器的原生字节序。

请注意,某些函数,如 inet_addr()gethostbyname()getaddrinfo() 报告已在网络字节中的 IPv4 地址顺序,所以不要对这些值使用 htonl()ntohl(),按原样使用它们。

然后,定义一个字节对齐的结构来保存您的消息数据,然后将其原样传递给sendto()不要将其转换为ostringstream。不要对 sendto() 需要一个 char* 这一事实感到困惑,这只是出于历史原因。它实际上需要原始字节,而不是字符串。

试试这个:

#pragma pack(push, 1) // or your compiler's equivalent

struct sMsgHeader
{
// General Message header fields here...
};

// ...

struct sRouteUpdateServer
{
uint32_t serverIP;
uint16_t serverPort;
uint16_t reserved;
uint16_t serverID;
uint16_t cost;
};

struct sRouteUpdateMsg
{
sMsgHeader header;
uint16_t numUpdateFields;
uint16_t serverPort;
uint32_t serverIP;
sRouteUpdateServer servers[some max value here];
};

#pragma pack(pop) // or your compiler's equivalent

sRouteUpdateMsg msg;
// fill msg.header as needed...

msg.numUpdateFields = htons(...);
msg.serverPort = htons(...);
msg.serverIP = ...;
for (int i = 0; i < numberOfServers; ++i)
{
msg.servers[i].serverIP = ...;
msg.servers[i].serverPort = htons(...);
msg.servers[i].reserved = 0;
msg.servers[i].serverID = htons(...);
msg.servers[i].cost = htons(...);
}

//...

sendto(..., (char*)&msg, sizeof(sMsgHeader)+8+(sizeof(sRouteUpdateServer)*numberOfServers), ...);

或者,如果您的编译器支持 offsetof()(或者您自己编写):

sendto(..., (char*)&msg, offsetof(sRouteUpdateMsg, servers)+(sizeof(sRouteUpdateServer)*numberOfServers), ...);

在接收方做相反的事情。使用recvfrom()接收消息数据,然后调用ntoh...()根据需要转换消息的多字节整数,然后处理消息。

关于c++ - 将 int 类型的结构放入 Big Endian 中的 ostream 以转换为 char *,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27083543/

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