网络通讯一般分为基于数据结构的和基于流的。HTTP协议就是后者的一个例子。
有时为了提升程序的处理速度和数据处理的方便,会使用基于数据结构的通讯(不须要对流进行解析)。可是,当须要在多平台间进行通讯时,基于数据结构的通讯,每每要十分注意如下几个方面:
[1] 字节序
[2] 变量长度
[3] 内存对齐
在常见的系统架构中(Linux X86,Windows),非单字节长度的变量类型,都是低字节在前,而在某些特定系统中,如Soalris Sparc平台,高字节在前。若是在发送数据前不进行处理,那么由Linux X86发向Soalris Sparc平台的数据值,势必会有极大的误差,进而程序运行过程当中没法出现预计的正常结果,更严重时,会致使段错误。
对于此种状况,咱们每每使用同一的字节序。在系统中,有ntohXXX(), htonXXX()等函数,负责将数据在网络字节序和本地字节序之间转换。虽然每种系统的本地字节序不一样,可是对于全部系统来讲,网络字节序是固定的 -----高字节在前。因此,能够以网络字节序为通讯的标准,发送前,数据都转换为网络字节序。
转换的过程,也建议使用ntohXXX(), htonXXX()等标准函数,这样代码能够轻松地在各平台间进行移植(像通讯这种不多依赖系统API的代码,作成通用版本是不错的选择)。
变量的长度,在不一样的系统之间会有差异,如同是Linux2.6.18的平台,在64位系统中,指针的长度为8个字节,而在32位系统中,指针又是4个字 节的长度---此处只是举个例子,不多有人会将指针做为数据发送出去。下面是我整理的在64位Linux系统和32位Linux系统中,几种常见C语言变 量的长度:
short int long long long ptr time_t
32位 2 4 4 8 4 4
64位 2 4 8 8 8 8
在定义通讯用的结构体时,应该考虑使用定常的数据类型,如uint32_t,4字节的固定长度,而且这属于标准C库(C99),在各系统中均可使用。
内存对齐的问题,也与系统是64位仍是32位有关。若是你手头有32位和64位系统,不妨写个简单的程序测试一下,你就会看到同一个结构体,即使使用了定 常的数据类型,在不一样系统中的大小是不一样的。对齐每每是以4字节或8字节为准的,只要你写的测试程序,变量所占空间没有对齐到4或8的倍数便可,举个简单 的测试用的结构体的例子吧:
struct student
{
char name[7];
uint32_t id;
char subject[5];
};
在每一个系统上看下这个结构体的长度吧。
内存对齐,每每是由编译器来作的,若是你使用的是gcc,能够在定义变量时,添加__attribute__,来决定是否使用内存对齐,或是内存对齐到几个字节,以上面的结构体为例:
1)到4字节,一样可指定对齐到8字节。
struct student
{
char name[7];
uint32_t id;
char subject[5];
} __attribute__ ((aligned(4)));
2)不对齐,结构体的长度,就是各个变量长度的和
struct student
{
char name[7];
uint32_t id;
char subject[5];
} __attribute__ ((packed));网络