gpt4 book ai didi

c - 如何将复杂数据类型从主机字节顺序转换为网络顺序

转载 作者:行者123 更新时间:2023-12-02 22:29:50 25 4
gpt4 key购买 nike

我想使用 htonl() 和 htos() 将消息从主机字节顺序转换为网络顺序。在这个消息中,有一些复杂的定义数据类型,如结构、枚举、 union 和 union 中的 union 。

  1. 我是否必须 htonl(s) 每个结构的成员和成员中的成员,包括多字节的 union 成员?
  2. 对于 union ,我可以只翻译最大的 union 吗?
  3. 对于枚举,我可以把它翻译成 long 吗?
  4. 我可以只编写一个使用 htonl(s) 发送和接收消息的函数吗?或者我是否必须想出另一个使用 ntohl(s) 来接收相同消息的方法?

结构

typedef struct {
unsigned short un1_s;
unsigned char un1_c;

union {
unsigned short un1_u_s;
unsigned long un1_u_l;
}u;
}UN1;

typedef struct {
unsigned short un2_s1;
unsigned short un2_s2;
} UN2;

typedef enum {
ONE,
TWO,
TRHEE,
FOUR
} ENUM_ID;

typedef struct {
unsigned short s_sid;
unsigned int i_sid;
unsigned char u_char;
ENUM_ID i_enum;

union {
UN1 un1;
UN2 un2;
} u;
} MSG;

代码

void msgTranslate (MSG* in_msg, MSG* out_msg){

/* ignore the code validating pointer ... */

*out_msg = *in_msg;

#ifdef LITLE_ENDIAN

/* translating messeage */
out_msg->s_sid = htons( in_msg->s_sid ); /* short */
out_msg->i_sid = htonl( in_msg->i_sid ); /* int */

/* Can I simply leave out_msg->u_char not to translate,
* because it is a single byte? */

out_msg->i_enum = htonl(in_msg->i_enum);
/* Can I simply translate a enum this way,? */

/* For an union whose 1st member is largest one in size than
* others, can I just translate the 1st one,
* leaving the others not to convert? */

out_msg->u.un1.un1_s = htons(in_msg->u.un1.un1_s);


/* for out_msg->u_char, can I simply leave it
* not to be converted, because it is a single byte? */

/* for an union whose 2nd member is largest one,
* can I just convert the 2nd one, leaving others
* not to be converted? */

out_msg->u.un1.u.un1_u_s = htos(in_msg->u.un1.u.un1_u_s ); /* short */

/* As above question, the following line can be removed?
* just because the u.un1.u.un2_u_i is smaller
* than u.un1.u.un1 in size ? */

out_msg->u.un1.u.un2_u_i = htol(in_msg->u.un1.u.un2_u_l ); /* long */

/* Since un1 is largest than un2, the coding translation un2 can be ignored? */
...

#endif

return;
}

最佳答案

  1. 您需要适本地映射每个多字节类型。

  2. 对于 union ,您需要确定哪个是 union 的“事件”元素,并根据正常规则映射它。您可能还需要提供一个“鉴别器”,它告诉接收代码传输了各种可能性中的哪一种。

  3. 对于枚举,您可以决定将所有此类值视为 long并相应地进行编码和解码。或者,您可以单独处理每个枚举,根据其大小处理每个类型(理论上,不同的枚举可以有不同的大小)。

  4. 这在一定程度上取决于您下一步真正要做什么。如果您正在打包数据以通过网络传输,那么接收和发送操作就大不相同了。如果您所做的只是翻转内存结构中的位,那么您可能会发现在大多数系统上,应用 htonl() 的结果对 htonl() 的结果的函数是你首先想到的数字。如果您打算对映射(翻转)结构中的所有字节进行二进制复制,那么您可能做得不对。

请注意,在大多数看似合理的系统上,您的数据结构中都有各种填充孔。在结构 UN1 中,您几乎可以肯定在 un1_c 之间有一个填充字节。和以下联盟 u , 如果是32位系统;如果它是 64 位系统,你可能在那里填充 5 个字节。同样,在 MSG结构,您可能在 s_sid 之后有 2 个填充字节, u_char 之后还有 3 个.取决于 enum 的大小(无论你是在 32 位还是 64 位机器上),你可能在 i_enum 之后有 1-7 个字节的填充。 .

请注意,因为您没有数据类型的平台独立大小,所以您无法在 32 位和 64 位 Unix 系统之间可靠地互通。如果系统都是 Windows,那么自 sizeof(long) == 4 之后你就可以摆脱它了。在 32 位和 64 位 Windows 上。然而,在基本上所有 64 位 Unix 变体上,sizeof(long) == 8 .因此,如果跨平台工作是一个问题,您必须担心这些尺寸以及填充。调查 <inttypes.h> 中的类型标题如 uint16_tuint32_t .

您应该在所有主机上简单地进行相同的打包,小心地将各种值的字节复制到字符缓冲区中的适当位置,然后通过网络发送并通过反向编码解包。

同时查看 Google 的 Protocol Buffers会明智地为您完成工作;它可能会为您省去相当多的痛苦和悲伤。

关于c - 如何将复杂数据类型从主机字节顺序转换为网络顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12469823/

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