Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将int类型的结构放入Big-Endian中的ostream以转换为char*_C++_Sockets_Serialization_Network Programming_Deserialization - Fatal编程技术网

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

C++ 将int类型的结构放入Big-Endian中的ostream以转换为char*,c++,sockets,serialization,network-programming,deserialization,C++,Sockets,Serialization,Network Programming,Deserialization,我在stdint.h中使用uintnt的struct实现了一个通过UDP套接字交换的消息 传递到UDP套接字的任何数据都必须是Big-Endian,当然也必须是char*或const-char*类型 我运行这个程序的系统是基于Little Endian的 我不熟悉序列化,基于以上的答案,我尝试了put()按与ostringstream相反的顺序对数据进行排序。(详见下面的代码) void put_u16_as_big(ostringstream&oss,uint16_t数据){ write((c

我在
stdint.h
中使用
uintnt
struct
实现了一个通过
UDP
套接字交换的消息

传递到UDP套接字的任何数据都必须是
Big-Endian
,当然也必须是
char*
const-char*
类型

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

我不熟悉序列化,基于以上的答案,我尝试了
put()
按与
ostringstream
相反的顺序对数据进行排序。(详见下面的代码)

void put_u16_as_big(ostringstream&oss,uint16_t数据){
write((const char*)和data,sizeof(data));
如果(是大的吗?){
write((const char*)和data,sizeof(data));
}
否则{
常量字符*ptr=(常量字符*)&数据;
无符号整数s=sizeof(数据);
for(无符号整数i=0;i
但是,当我将struct中的所有数据放在
ostringstream
的一个实例中并调用
str()
方法时,数据的大小不是它应该的大小(小于8字节*2+8字节*3*所有服务器的数量,如上表所示),并且
data()
方法从该字符串中进一步缩小(到8)

最后,当在另一侧接收时,大小为1

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

struct
包含类型为
uint16\u t
uint32\u t
的字段,以及另一个结构的向量(用于服务器列表),该结构还包含
uint16\u t
uint32\u t
int16\u t

请帮帮我。我已经努力解决这个问题好几天了,但是运气不好


谢谢。

使用套接字API
htons()
(主机到网络短)和
htonl()
(主机到网络长)函数将多字节整数从本地计算机的本机端号转换为网络字节顺序(big-endian)。在big-endian系统上,该操作是不可操作的。在little-endian系统上,字节交换。您可以使用
ntohs()
(网络到主机短)和
ntohl()
(网络到主机长)将多字节整数从网络字节顺序转换为本地计算机的本机endian

请注意,有些函数,如
inet\u addr()
gethostbyname()
getaddrinfo()
报告的IPv4地址已按网络字节顺序排列,因此不要对这些值使用
htonl()
ntohl()
,请按原样使用它们

然后,定义一个字节对齐的
struct
来保存消息数据,然后按原样将其传递给
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


在接收端进行反向操作。使用
recvfrom()
接收消息数据,然后根据需要调用
ntoh…()
转换消息的多字节整数,然后再处理消息。

ostringstream
是完全错误的方法,甚至不要查看它。这不是序列化问题,这是字节尾数问题,这正是
hton…()
ntoh…()
所要处理的。不,您不能将
向量
放入发送的结构中。不过,固定长度的数组可以工作。只要确保在调用
sendto()
时,根据服务器的数量指定正确的消息大小,例如
sizeof(header)+6+(sizeof(server)*numberOfServers)
,不要使用
sizeof(msg)
。6是前3个字段的大小-
更新字段的数量
服务器端口
,和
服务器IP
-在每服务器字段之前。是的,只要考虑到未使用的字段,就可以将未使用的字段留空。是的,应该是8,而不是6,对不起。但是不可以,除非您发送的服务器数量与
sRouteUpdateMsg
实际容纳的最大服务器数量相同,否则传递给
sendto()
的消息大小不会是
sizeof(sRouteUpdateMsg)
的完整大小。
servers
数组是
sRouteUpdateMsg
的一部分,并将由
sizeof>计算完整大小(sRouteUpdateMsg)
。这就是为什么您必须将
sRouteUpdateMsg
的内容计算到
服务器
数组,但不包括该数组,然后分别计算实际发送的
服务器
数组中的项目数。我之所以一直提到一个单独的标题,是因为您的图表说明:“数据部分的消息格式为”,这意味着有一个消息头与您提供的图表分开描述。
#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), ...);
sendto(..., (char*)&msg, offsetof(sRouteUpdateMsg, servers)+(sizeof(sRouteUpdateServer)*numberOfServers), ...);