C 小端系统中大端系统发送的结构数据的反序列化

C 小端系统中大端系统发送的结构数据的反序列化,c,sockets,endianness,C,Sockets,Endianness,我有一个C程序,它通过套接字以UDP数据包的形式从大型机接收数据。C程序的主机正在从Unix(big-endian)更改为Linux(little-endian),程序不再工作。我目前没有更改大型机客户端程序的选项 程序执行recvfrom,并将数据接收到字符数组中。在此之前,我们能够简单地将这个缓冲区转换为与MF传递的内容相匹配的结构,并且一切工作都很完美。现在,由于不同的字节对齐方式,到结构的映射失败。下面是结构和一些代码 struct CCClntPkt { unsigned sh

我有一个C程序,它通过套接字以UDP数据包的形式从大型机接收数据。C程序的主机正在从Unix(big-endian)更改为Linux(little-endian),程序不再工作。我目前没有更改大型机客户端程序的选项

程序执行
recvfrom
,并将数据接收到字符数组中。在此之前,我们能够简单地将这个缓冲区转换为与MF传递的内容相匹配的结构,并且一切工作都很完美。现在,由于不同的字节对齐方式,到结构的映射失败。下面是结构和一些代码

struct CCClntPkt
{
    unsigned short packet_type;
    unsigned short reply_socket;
    unsigned long  msg_ID;
    unsigned short msg_length;
    unsigned char  client_string[250];
};
以前用于将接收到的数据缓冲区强制转换到此结构的代码如下所示:

char BCpacket_in[MAX_PACKET];
struct CCClntPkt *pClntPkt;

<snip>

rcv_cnt = recvfrom(BCServerSocket, BCpacket_in,
                sizeof(BCpacket_in),0x0,(struct sockaddr *)&from,
                &fromlen);

if (rcv_cnt > 0)
{
    pClntPkt = (struct CCClntPkt *) &BCpacket_in;
}

我在这一点上很难办,所以任何帮助都是感激的。我不是这个程序的原始作者,我的C语言知识非常有限。我不介意做这项工作,所以我也希望能得到任何相关的参考资料。谢谢

您必须手动将接收到的数据包(
BCpacket\u in
)解析为
struct-CCClntPkt
数据包,这是唯一可移植的方法。使用
ntohl
(网络到主机
long
)函数系列正确处理Endianness转换;请参阅手册页
byteorder(3)
endian(3)


这些函数假定所有数据包都以big-endian的形式通过网络发送,因为这是互联网标准。

您必须手动将接收到的数据包(
BCpacket\u in
)解析为
struct CCClntPkt
数据包,这是唯一可移植的方法。使用
ntohl
(网络到主机
long
)函数系列正确处理Endianness转换;请参阅手册页
byteorder(3)
endian(3)


这些函数假定所有数据包都以big-endian的形式通过网络发送,因为这是互联网标准。

这是我通常对发送到/从网络接收到的压缩结构所做的:

#define PACKED __attribute__((__packed__))
struct PACKED message { ... };

这是特定于GCC的,请参阅。然后,您必须计算出
的大小。它在32位和64位平台上有所不同。您可能希望研究使用类型。另请查看信息。

这是我通常对发送到/从网络接收到的打包结构所做的操作:

#define PACKED __attribute__((__packed__))
struct PACKED message { ... };

这是特定于GCC的,请参阅。然后,您必须计算出
的大小。它在32位和64位平台上有所不同。您可能希望研究使用类型。另请查看信息。

msg_ID=BCpacket_in[4]
msg_ID=BCpacket_in[4]从大端主机到新的小端主机,各种类型的大小可能不同

如果在两台主机上编译此程序,它将显示结构的大小和布局

#include <stddef.h>
#include <stdio.h>

struct CCClntPkt
{
    unsigned short packet_type;
    unsigned short reply_socket;
    unsigned long  msg_ID;
    unsigned short msg_length;
    unsigned char  client_string[250];
};

int main()
{
    printf("sizeof(unsigned short) = %u\n", (unsigned)sizeof(unsigned short));
    printf("sizeof(unsigned long) = %u\n", (unsigned)sizeof(unsigned long));

    printf("offsetof(struct CCClntPkt, reply_socket) = %u\n", (unsigned)offsetof(struct CCClntPkt, reply_socket));
    printf("offsetof(struct CCClntPkt, msg_ID) = %u\n", (unsigned)offsetof(struct CCClntPkt, msg_ID));
    printf("offsetof(struct CCClntPkt, msg_length) = %u\n", (unsigned)offsetof(struct CCClntPkt, msg_length));
    printf("offsetof(struct CCClntPkt, client_string) = %u\n", (unsigned)offsetof(struct CCClntPkt, client_string));

    return 0;
}
#包括
#包括
结构CCClntPkt
{
无符号短数据包类型;
无符号短应答\u套接字;
未签名的长消息\u ID;
无符号短消息长度;
无符号字符客户端_字符串[250];
};
int main()
{
printf(“sizeof(unsigned short)=%u\n”,(unsigned)sizeof(unsigned short));
printf(“sizeof(unsigned long)=%u\n”,(unsigned)sizeof(unsigned long));
printf(“offsetof(struct CCClntPkt,reply_socket)=%u\n”,“offsetof(struct CCClntPkt,reply_socket)(未签名));
printf(“offsetof(struct CCClntPkt,msg_ID)=%u\n”,未签名)offsetof(struct CCClntPkt,msg_ID));
printf(“offsetof(struct CCClntPkt,msg_length)=%u\n”,“未签名的”offsetof(struct CCClntPkt,msg_length));
printf(“offsetof(struct CCClntPkt,client_string)=%u\n”(未签名)offsetof(struct CCClntPkt,client_string));
返回0;
}
特别是,很可能新主机上的
long
比旧主机上的长。这可能是使用
中的C99精确宽度类型的好地方-如果在原始主机上,
short
是16位类型,
long
是32位类型,请分别用
uint16_t
uint32_t
替换这些类型


然后,您可以使用
ntohs()
ntohl()
执行尾端校正。

不同类型的主机的大小可能不同于新的大尾端主机

如果在两台主机上编译此程序,它将显示结构的大小和布局

#include <stddef.h>
#include <stdio.h>

struct CCClntPkt
{
    unsigned short packet_type;
    unsigned short reply_socket;
    unsigned long  msg_ID;
    unsigned short msg_length;
    unsigned char  client_string[250];
};

int main()
{
    printf("sizeof(unsigned short) = %u\n", (unsigned)sizeof(unsigned short));
    printf("sizeof(unsigned long) = %u\n", (unsigned)sizeof(unsigned long));

    printf("offsetof(struct CCClntPkt, reply_socket) = %u\n", (unsigned)offsetof(struct CCClntPkt, reply_socket));
    printf("offsetof(struct CCClntPkt, msg_ID) = %u\n", (unsigned)offsetof(struct CCClntPkt, msg_ID));
    printf("offsetof(struct CCClntPkt, msg_length) = %u\n", (unsigned)offsetof(struct CCClntPkt, msg_length));
    printf("offsetof(struct CCClntPkt, client_string) = %u\n", (unsigned)offsetof(struct CCClntPkt, client_string));

    return 0;
}
#包括
#包括
结构CCClntPkt
{
无符号短数据包类型;
无符号短应答\u套接字;
未签名的长消息\u ID;
无符号短消息长度;
无符号字符客户端_字符串[250];
};
int main()
{
printf(“sizeof(unsigned short)=%u\n”,(unsigned)sizeof(unsigned short));
printf(“sizeof(unsigned long)=%u\n”,(unsigned)sizeof(unsigned long));
printf(“offsetof(struct CCClntPkt,reply_socket)=%u\n”,“offsetof(struct CCClntPkt,reply_socket)(未签名));
printf(“offsetof(struct CCClntPkt,msg_ID)=%u\n”,未签名)offsetof(struct CCClntPkt,msg_ID));
printf(“offsetof(struct CCClntPkt,msg_length)=%u\n”,“未签名的”offsetof(struct CCClntPkt,msg_length));
printf(“offsetof(struct CCClntPkt,client_string)=%u\n”(未签名)offsetof(struct CCClntPkt,client_string));
返回0;
}
特别是,很可能新主机上的
long
比旧主机上的长。这可能是使用
中的C99精确宽度类型的好地方-如果在原始主机上,
short
是16位类型,
long
是32位类型,请分别用
uint16_t
uint32_t
替换这些类型


然后,您可以使用
ntohs()
ntohl()
执行尾端更正。

您注释掉的代码应该可以执行此操作,假设它是