Linux网络编程——字节序、地址转换函数

1 .谈到字节序,那么会有朋友问什么是字节序
很简单:【例如一个16位的整数,由2个字节组成,8位为一字节,有的系统会将高字节放在内存低的地址上,有的则将低字节放在内存高的地址上,所以存在字节序的问题。】

2 .那么什么是高字节、低字节?
也相当简单:【一个16进制整数有两个字节组成,例如:0xA9。
高字节就是指16进制数的前8位(权重高的8位),如上例中的A。
低字节就是指16进制数的后8位(权重低的8位),如上例中的9。】
大于一个字节的变量类型一般有两种表示方法:

字节序是指多字节数据的存储顺序,在设计计算机系统的时候,有两种处理内存中数据的方法:大端格式、小端格式。

小端格式(Little-Endian):将低位字节数据存储在低地址。
大端格式(Big-Endian):将高位字节数据存储在低地址。

例如:变量0xabcd在大端字节序和小端字节型系统中表示方法如图

我们用代码验证一下我们自己的系统是小端还是大端吧

可以查看:https://baike.baidu.com/item/%E5%AD%97%E8%8A%82%E5%BA%8F/1457160?fr=aladdin      X86都是小端字节序    网络字节序都是大端字节序

#include <stdio.h>

/* 联合类型的变量类型,用于测试字节序
*   成员value的高低端字节可以由成员type按字节访问
 */
typedef union{
    unsigned short int value;                               /*短整型变量*/
    unsigned char byte[2];                              /*字符类型*/
}to;

int main(int argc, char *argv)
{   
    to typeorder ;                                      /*一个to类型变量*/
    typeorder.value = 0xabcd;                               /* 将typeorder变量赋值为0xabcd */

    /* 小端字节序检查 */
    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]); 
    }

    /* 大端字节序检查 */
    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;   
}

3 .字节序转换函数介绍

字节序转换函数的使用:

#include <stdio.h>

/* 联合类型的变量类型,用于测试字节序
*   成员value的高低端字节可以由成员type按字节访问
 */
/* 16位 */
typedef union{
    unsigned short int value;
    unsigned char byte[2];  
}to16;
/* 32位 */
typedef union{
    unsigned long int value;
    unsigned char byte[4];  
}to32;

#define BITS16 16   /*16位*/
#define BITS32 32   /*32位*/
/* 按照字节打印,begin为字节开始,
*  flag为BITS16表示16位,
*  flag为BITS32表示32位, 
*/
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; /*一个to16类型变量*/
    to32 v32_orig, v32_turn1,v32_turn2; /*一个to32类型变量*/


    v16_orig.value = 0xabcd;        /* 赋值为0xabcd */
    v16_turn1.value = htons(v16_orig.value);/*第一次转换*/
    v16_turn2.value = ntohs(v16_turn1.value);/*第二次转换*/

    v32_orig.value = 0x12345678;    /* 赋值为0x12345678 */
    v32_turn1.value = htonl(v32_orig.value);/*第一次转换*/
    v32_turn2.value = ntohl(v32_turn1.value);/*第二次转换*/

    /* 打印结果 */
    printf("16 host to network byte order change:\n");  
    printf("\torig:\t");showvalue(v16_orig.byte, BITS16);   /* 16位数值的原始值 */
    printf("\t1 times:");showvalue(v16_turn1.byte, BITS16); /* 16位数值的第一次转换后的值 */
    printf("\t2 times:");showvalue(v16_turn2.byte, BITS16); /* 16位数值的第二次转换后的值 */

    printf("32 host to network byte order change:\n");
    printf("\torig:\t");showvalue(v32_orig.byte, BITS32);   /* 32位数值的原始值 */
    printf("\t1 times:");showvalue(v32_turn1.byte, BITS32); /* 32位数值的第一次转换后的值 */
    printf("\t2 times:");showvalue(v32_turn2.byte, BITS32); /* 32位数值的第二次转换后的值 */


    return 0;   
}

地址转换函数

以下接口所需头文件:#include <arpa/inet.h>

int inet_pton(int family, const char *strptr, void *addrptr);

功能:

将点分十进制数串转换成 32 位无符号整数

参数:

family:协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET

strptr:点分十进制数串

addrptr:32 位无符号整数的地址

返回值:

成功返回 1 、 失败返回其它

测试示例:


#include <stdio.h>

#include <arpa/inet.h>

int main()

{

    char ip_str[]="172.20.223.75";

    unsigned int ip_uint = 0;

    unsigned char *ip_p = NULL;


    inet_pton(AF_INET,ip_str,&ip_uint);

    printf("in_uint = %d\n",ip_uint);


    ip_p = (char *)&ip_uint;

    printf("in_uint = %d,%d,%d,%d\n",*ip_p,*(ip_p+1),*(ip_p+2),*(ip_p+3));


    return 0;

}



运行结果如下:

 

const char *inet_ntop( int family, const void *addrptr,  char *strptr, size_t len );

功能:

将 32 位无符号整数转换成点分十进制数串

参数:

family:协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET

addrptr:32 位无符号整数

strptr:点分十进制数串

len:strptr 缓存区长度

len 的宏定义
#define INET_ADDRSTRLEN   16  // for ipv4

#define INET6_ADDRSTRLEN  46  // for ipv6

返回值:

成功:则返回字符串的首地址

失败:返回 NULL

测试示例:

#include <stdio.h>

#include <arpa/inet.h>

int main()

{

    unsigned char ip[] = {172,20,223,75};

    char ip_str[16] = "NULL";


    inet_ntop(AF_INET,(unsigned int *)ip,ip_str,16);

    printf("ip_str = %s\n",ip_str);

    return 0;

}

运行结果如下:

 

 

 

感谢博文 https://blog.csdn.net/hnlyyk/article/details/47974027

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值