网络字节序和IP地址详解

Linux网络编程 专栏收录该内容
22 篇文章 12 订阅

一、网络字节序

1、大端模式和小端模式

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

  • 小端格式(Little-Endian):将低位字节数据存储在低地址;
  • 大端格式(Big-Endian):将高位字节数据存储在低地址。
    在这里插入图片描述

  举个简单的例子,对于整形 0x12345678,它在大端格式和小端格式的系统中,分别如下图所示的方式存放:
在这里插入图片描述

2、判断大端模式和小端模式

【下面例子为确定主机的字节序】:

#include <stdio.h>  
int main(int argc, charchar *argv[])  
{  
    unsigned int a = 0x12345678;  
    unsigned char *p = (unsigned char *)&a; // 取低地址上的数据
    if(0x12 == *p){  
        printf("Big-Endian\n");  
    }else if(0x78 == *p){  
        printf("Little-Endian\n");  
    }  
    return 0;  
}  

  网络字节序定义:收到的第一个字节被当作高位看待,这就要求发送端发送的第一个字节应当是高位。而在发送端发送数据时,发送的第一个字节是该数字在内存中起始地址对应的字节。可见多字节数值在发送前,在内存中数值应该以大端法存放。

  所以,网络协议指定了通讯字节序:大端只有在多字节数据处理时才需要考虑字节序,运行在同一台计算机上的进程相互通信时,一般不用考虑字节序,异构计算机之间通讯,需要转换自己的字节序为网络字节。主机字节序是小端,所以才需要进行字节序转换。

3、大端模式和小端模式相互转换

  使用移位运算:

uint32_t reversebytes_uint32t(uint32_t value){
    return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 | 
        (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24; 
}
上述代码中,将低8位(0~8位)左移24位,变成了高8位(24~32位),8~16位左移8位变成了
(16~24位)。将原高8位和高16位右移,变成了新的低8位和低16位。

二、字节序转换函数

#include <arpa/inet.h>
// 将 32位主机字节序数据转换成网络字节序数据
//(h:host, n:net,l:long)
uint32_t htonl(uint32_t hostint32);
// 将 16 位主机字节序数据转换成网络字节序数据
uint16_t htons(uint16_t hostint16);
// 将 32 位网络字节序数据转换成主机字节序数据
uint32_t ntohl(uint32_t netint32);
// 将 16 位网络字节序数据转换成主机字节序数据
uint16_t ntohs(uint16_t netint16);

三、IP地址详解

1、IP地址的概念

  IP地址分为网络IP和主机IP:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • A类地址第一字节为网络ID,后三个字节为主机ID,范围是1.0.0.0到126.255.255.255; 默认子网掩码:255.0.0.0;

  • B类地址第一二字节为网络ID,后两个字节为主机ID,范围是128.0.0.0到191.255.255.255; 默认子网掩码:255.255.0.0;

  • C类地址前三个字节为网络ID,最后一个字节为主机ID,范围是192.0.0.0到223.255.255.255;默认子网掩码:255.255.255.0;

  • D类地址用于组播,前四位为1110,范围是224.0.0.0到239.255.255.255;

  • E类地址用于研究,前五位为11110,范围是240.0.0.0到247.255.255.255。

2、IP地址的两种表示方法:整数和点分十进制

点分十进制->整数:点分十进制->十六进制->十进制(整数)。

整数->点分十进制:十进制(整数)->十六进制->每个字节转换为十进制(整数)。

3、判断IP地址是否合法

  • IP的格式为:(1~255).(0~255).(0~255).(0~255)

  • 以小数点开头为非法IP,如:.x.x.x.或者.x.x.xx;

  • 以小数点结尾为非法IP,如:x.x.x.x.;

  • 输入带0开头为非法IP,如:0x.0xx.0x.00x。

四、IP地址转换

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

#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 charchar *ip_p = NULL;  
  
    inet_pton(AF_INET,ip_str,&ip_uint);  
    printf("in_uint = %d\n",ip_uint);  
      
    ip_p = (charchar *)&ip_uint;  
    printf("in_uint = %d,%d,%d,%d\n",*ip_p,
    	*(ip_p+1),*(ip_p+2),*(ip_p+3));  
  
    return 0;  
} 

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

#include <arpa/inet.h>
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 缓存区长度;
      • #define INET_ADDRSTRLEN 16 // for ipv4
      • #define INET6_ADDRSTRLEN 46 // for ipv6
  • 返回值: 成功:则返回字符串的首地址,失败:返回 NULL

转自:https://blog.csdn.net/lianghe_work/article/details/45170285
https://blog.csdn.net/Esther_Heesch/article/details/51476811
https://blog.csdn.net/weixin_36525275/article/details/79456065
https://blog.csdn.net/u014259820/article/details/78833196

  • 2
    点赞
  • 0
    评论
  • 19
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值