Linux网络编程——字节序与网络字节序[通俗易懂]

Linux网络编程——字节序与网络字节序[通俗易懂]字节序相关概念  什么是字节序?  字节序是由于不同主处理器(CPU)和操作系统(OS)对多字节的变量在内存中存放顺序的不同而产生的。  字节序的分类?一般分为两类:  ①小端字节序(LittleEndian,LE):变量的内存地址起始地址存放低字节,高字节顺序存放  ②大端字节序(BigEndian,BE):变量的内存地址起始地址存放高字节,低字节顺序存放  实例:…

说明
  本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
  QQ 群 号:513683159 【相互学习】
内容来源
  《Linux网络编程》
内容概述
  简单介绍字节序与网络字节序的概念
  两个示例:
    1.检查本机字节序
    2.字节序转换

字节序概念

  什么是字节序?
  字节序是由于不同主处理器(CPU)和操作系统(OS)对多字节的变量在内存中存放顺序的不同而产生的。
  字节序的分类?一般分为两类:
  ①小端字节序(Little Endian,LE):变量的内存地址起始地址存放低字节,高字节顺序存放
  ②大端字节序(Big Endian, BE):变量的内存地址起始地址存放高字节,低字节顺序存放
  实例Linux网络编程——字节序与网络字节序[通俗易懂]

示例:检查本机字节序

源代码:check_order.c

#include <stdio.h>

/** * 字节序结构变量 * 联合类型的变量:所有成员占用同一段内存,修改一个成员会影响其他成员。 * 成员value高低端字节可由成员type按字节访问 */
typedef union
{ 
   
    unsigned short int value;           //短整型变量
    unsigned char byte[2];              //字符类型
}to;

int main(int argc,char *argv[])
{ 
   
    /** * 变量声明与赋值 * Note: value 和 byte成员共享同一块内存, * 故可通过byte的不同成员访问value的高低字节 */
    to typeorder;
    typeorder.value = 0xabcd;

    /** * 计算字节序结构中成员字节大小 */
    printf("Byte size:value = %ld,byte[0] = %ld\n",sizeof(typeorder.value),sizeof(typeorder.byte[0]));

    /** * 小端字节序检查 * 小端字节序(LE):起始地址存放低字节,高字节顺序存放 * Note: * 低字节 = byte[1]: 0xab * 高字节 = byte[0]: 0xcd */
    if(typeorder.byte[0] == 0xcd && typeorder.byte[1] == 0xab)
    { 
   
        printf("Low endian byte order byte[0]:0x%x,byte[1]:0x%x\n",
         typeorder.byte[0],typeorder.byte[1]);
    }
    /** * 大端字节序检查 * 大端字节序(BE):起始地址存放高字节,低字节顺序存放 * Note: * 低字节 = byte[1]: 0xcd * 高字节 = byte[0]: 0xab */
    if(typeorder.byte[0] == 0xab && typeorder.byte[1] == 0xcd)
    { 
   
        printf("High endian byte order byte[0]:0x%x,byte[1]:0x%x\n",
         typeorder.byte[0],typeorder.byte[1]);
    }

    return 0;
}

编译并运行

  编译
    执行指令:gcc check_order.c -o check_order
  运行
    执行指令:./check_order
  结果

Byte size:value = 2,byte[0] = 1
Low endian byte order byte[0]:0xcd,byte[1]:0xab

  很明显,我的系统是小端字节序。

网络字节序概念

  网络字节序:多字节变量在网络传输时的表示方法,采用的是:高端字节序。
  这是由于主机千差万别,故主机字节序不能做到统一,故对于网络传输的变量必须有一个统一的表示方法。
  故为程序设计方便,让程序与平台无关,可在网络传输前先对字节序进行转换。

字节序转换函数

  函数位置:netinet/in.h
  主机和网络字节顺序之间转换的函数,如下:
  htonl()–“Host to Network Long” —— 主机字节序到网络字节序的长整型转换
  htons()–“Host to Network Short” ——主机字节序到网络字节序的短整型转换
  ntohl()–“Network to Host Long” —— 网络字节序到主机字节序的长整型转换
  ntohs()–“Network to Host Short” —— 网络字节序到主机字节序的短整型转换
  可知,函数命名规则为:字节序 to 字节序 变量类型

htonl()函数

  函数功能:将主机的无符号长整形数转换成网络字节顺序。

项目 说明
函数原型 extern uint32_t htonl (uint32_t __hostlong) __THROW __attribute__ ((__const__));
头文件 netinet/in.h
参数说明 __hostlong:主机字节顺序表达的32位数
返回值 返回一个网络字节顺序的值
注意

htons()函数

  函数功能:将主机的无符号短整形数转换成网络字节顺序。

项目 说明
函数原型 extern uint16_t htons (uint16_t __hostshort) __THROW __attribute__ ((__const__));
头文件 netinet/in.h
参数说明 __netshort:主机字节顺序表达的16位数
返回值 返回一个网络字节顺序的值。
注意

ntohl()函数

  函数功能:将一个32位数由网络字节顺序转换为主机字节顺序。

项目 说明
函数原型 extern uint32_t ntohl (uint32_t __netlong) __THROW __attribute__ ((__const__));
头文件 netinet/in.h
参数说明 __netlong:主机字节顺序表达的32位数
返回值 返回一个以主机字节顺序表达的数
注意

ntohs()函数

  函数功能:将一个无符号短整形数从网络字节顺序转换为主机字节顺序。

项目 说明
函数原型 extern uint16_t ntohs (uint16_t __netshort) __THROW __attribute__ ((__const__));
头文件 netinet/in.h
参数说明 __netshort:主机字节顺序表达的16位数
返回值 返回一个以主机字节顺序表达的数
注意

示例:字节序转换

源代码:turn_order.c

#include <stdio.h>
#include <netinet/in.h>
#define BITS16 16
#define BITS32 32

/** * @union: 16位字节序结构变量 * 联合类型的变量:所有成员占用同一段内存,修改一个成员会影响其他成员。 * 成员value高低端字节可由成员type按字节访问 */
typedef union
{ 
   
    unsigned short int value;           //16位短整型变量
    unsigned char byte[2];              //字符类型
}to16;


/** * @union: 32位字节序结构变量 * 联合类型的变量:所有成员占用同一段内存,修改一个成员会影响其他成员。 * 成员value高低端字节可由成员type按字节访问 */
typedef union
{ 
   
    unsigned int value;                 //32位整型变量
    unsigned char byte[4];              //字符类型
}to32;

/** * @function: 变量值打印函数 * * @description: * 从变量存储空间的第一个字节开始,按照字节打印 * * @param begin: 变量的地址指针 * @param flag : 表示字长的标志变量 * BITS16 :打印16位变量的值 */
void showvalue(unsigned char *begin, int flag)
{ 
   
    int num = 0,i = 0;
    if(flag == BITS16)
    { 
   
        num = 2;
    }
    else if(flag == BITS32)
    { 
   
        num = 4;    
    }
    
    for(i = 0;i < num; i++)
    { 
   
        printf("%x ",*(begin+i));
    }
    printf("\n");
}

int main(int argc,char *argv[])
{ 
   
    /** * 字节序变量定义 */
    to16 v16_orig, v16_turn1, v16_turn2;                
    to32 v32_orig, v32_turn1, v32_turn2;

    /** * 16位变量 */
    v16_orig.value = 0xabcd;                            //原始值赋值
    v16_turn1.value = htons(v16_orig.value);            //第一次转换的值
    v16_turn2.value = htons(v16_turn1.value);           //第二次转换的值

    /** * 32位变量 */
    v32_orig.value = 0x12345678;                        //原始值赋值
    v32_turn1.value = htonl(v32_orig.value);            //第一次转换的值
    v32_turn2.value = htonl(v32_turn1.value);           //第二次转换的值

    /** * 16位变量两次字节序转换结果输出: */
    printf("16 host to network byte order change:\n");
    printf("\t orig:\t");   
    showvalue(v16_orig.byte,BITS16);                     //16位数据的原始值

    printf("\t 1 times:");
    showvalue(v16_turn1.byte,BITS16);                    //16位数据的第一次转换后的值

    printf("\t 2 times:");
    showvalue(v16_turn2.byte,BITS16);                    //16位数据的第二次转换后的值

    /** * 32位变量两次字节序转换结果输出: */
    printf("32 host to network byte order change:\n");
    printf("\t orig:\t");
    showvalue(v32_orig.byte,BITS32);                     //32位数据的原始值 

    printf("\t 1 times:");
    showvalue(v32_turn1.byte,BITS32);                    //32位数据的第一次转换后的值

    printf("\t 2 times:");
    showvalue(v32_turn2.byte,BITS32);                    //32位数据的第二次转换后的值


    return 0;
}

编译并运行

  编译
    执行指令:gcc turn_order.c -o turn_order
  运行
    执行指令: ./turn_order
  结果

16 host to network byte order change:
	 orig:	cd ab 
	 1 times:ab cd 
	 2 times:cd ab 
32 host to network byte order change:
	 orig:	78 56 34 12 
	 1 times:12 34 56 78 
	 2 times:78 56 34 12 

  值得注意的是:
    上面情形是在小端字节序系统上的结果,会发生改变。
    但是在大端字节序系统上,及时调用字节序转换函数也是不会发生改变的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/10745.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注