网络数据传输需注意的三个问题

来源:互联网 发布:app网站数据统计工具 编辑:程序博客网 时间:2024/06/02 02:52

         网络数据传送有两种方式:数据结构方式和数据流方式。一般数据流方式比较通用,但是有时侯也需要通过数据结构方式传送网络数据。使用数据结构方式传递数据一般都会将定义成一个结构体类型,如下所示

struct NetworkData{uint32_t length;  //数据长度void *data;  //传输数据}

       通信双方定义协定好的数据类型,通过Tcp/Ip进行socket通信。在使用数据结构方式进行通信时,要注意以下三方面:

1)网络字节序和主机字节序

       在不同平台下,数据存储的方有大端序和小端序两种。大端序是将数据的高位字节存放在地址的低端,低位字节存放在地址高端。小端序则相反,将数据的低位字节存放在地址的低端,高位字节存放在地址高端。例如,对于32位int型数据:0x01020304,其首地址为0x00000001,若以大端序方式存储,则为
   0x00000001   --01
   0x00000002   --02
   0x00000003   --03
   0x00000004   --04
   而小端序则为
   0x00000001   --04
   0x00000002   --03
   0x00000003   --02
   0x00000004   --01
   一种简便的记忆方式为:大端序按照书写顺序在内存中进行存储,而小端序则是按照逆书写顺序进行存储的。可以通过以下代码判断是大端序和小端序存储
int main(int argh, char **argv){    short temp = 0x1234;    if((*(unsigned char*)&temp) == 1)       printf("This is big endian\n");    else if((*(unsigned char*)&temp) == 4)       printf("This is little endian");    else       printf("Error!");;       return 0;}

           在网络通信中,数据统一按照大端序,即网络字节序。在进行数据传输时,发送数据时,将数据转成网络字节序(htons、htonl),接受数据时,再将数据转回主机子节序(ntohl、ntohs)。这样就避免了不同字节序造成的数据影响。

2)数据类型大小

        在windows和linux的32位和64位系统中,常用数据类型长度如下图所示

            win32  win64  Linux32  Linux64

char            1     1     1    1

short           2     2     2    2

int               4     4     4    4

long            4     4     4    8

long long    8     8     8    8

size_t         4     4     8    8

       需要特别注意的是,long int类型在windows64位系统中是4个字节,而在Linux系统中是8个字节。size_t类型数据与系统有关。因此,在进行跨平台网络数据传输时,尽量不要使用与平台相关的数据。应该使用定常的数据类型,如uint32_t,uint64_t等固定长度的数据这些数据属于标准C库(C99),各系统中大小均一致。

3)内存补齐

先看一个比较流行的计算结构体大小的题目:

#pragma pack(8)    //默认采用8字节对齐参数struct s1{    short a;    long b;};struct s2{    char c;    s1 d;    long long e;};#pragma pack(pop)  //恢复上一字节对齐参数

注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。

结构体s2的大小是多少呢?sizeof(s2) = 24

怎么得到的呢?首先我们计算s1的大小。s1中,默认对齐参数为8,对于每个变量而言,取自身对齐参数和默认对齐参数的最小值作为自身的对齐参数,因此,a对齐参数为2,b为4,而对于整个结构体而言,对齐方式为所有对齐参数中的最大值,因此取4字节对齐方式,所以,a补齐两个字节,b不变,因此s1的大小为8。再来计算s2的大小,c对齐参数为1,结构体s1字节对齐参数为所有成员的最大值,即为long 型对齐参数,所以d对齐参数为4,e对齐参数为8,所以,s2对齐方式为8字节对齐方式,因此,c补齐7个字节,d补齐4个字节,e不需要补齐,所以sizeof(s2) = 24。

总结一下,内存对齐方式的特点:

1、每个成员采用自身对齐参数

2、结构体类型对齐参数时所有成员对齐参数的最大值

3、结构体类型对齐后,对齐长度为最大对齐参数的整数倍,不够的补齐

若将对齐方式改为4字节对齐,则sizeof(s2)等于多少呢?

#pragma pack(4)    //采用4字节对齐参数struct s1{    short a;    long b;};struct s2{    char c;    s1 d;    long long e;};#pragma pack(pop) 
我们分析一下,对于s1,对齐参数为4,sizeof(s1) = 8。对于s2而言,e的对齐参数变为4,而不再是8。所以s2的对齐参数为4,c补齐3个字节,d、e均不需补齐,所以sizeof(s2) = 16。

0 0
原创粉丝点击