1. 字节序

  之前我们在学习内存的时候可知,内存存储数据也是有大端存储和小端存储的,对于网络数据流同样有大端小端之分,那么为什么要定义网络字节序呢?

  原因是让不同cpu架构的计算机进行网络通信时,字节序不会混淆,因此tcp/ip协议规定了在网络中传输的字节流数据采用大端字节序。


图1-大端字节序

  通常,发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存(即先发出的数据是低地址,后发出的数据是高地址)。

2. 网络字节序转换函数

  对于有的计算机内部使用的字节序与网络字节序不同的,就需要对数据进行转换,比如ip地址,端口号,那么可以使用下面的转换函数。

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

  上面这四个函数中uint32_t表示无符号32位整数,你会发现这几个函数都长得很类似,其中在这些函数中,h表示主机,n表示网络,to表示转换到,l表示32位长整数的ip地址,s表示16位短整数的端口号。

  这里肯定会有一些同学有疑问,那么ip地址为什么是占32位,端口号是占16位呢?

  这是因为ip地址的格式是:255.255.255.255,公共分为4个部分,每一部分占1字节,1字节占8bit位,那么1个ip地址用2机制表示就是32bit位了。

  由于端口号最大能表示65535号,那么把65535换算成2进制就是2^16 - 1,也就是16个bit位了。

3. ip地址是什么

  生活中人们通常需要知道自己的居住地址,在网络中的同样需要一个地址来唯一标识每一台主机,这样所有的设备之间才能实现全球通信,ip地址就是标识了一台主机或路由设备在因特网的位置,并且互联网中的所有主机都要遵守这个ip地址结构。ip协议就可以通过ip地址结构把数据转发到互联网中的目的主机。

4. ip地址表示方法

一般ip地址的表示方法有以下三种:
  二进制记法(1000 0001 0000 1011 0000 1011 11101111),每8bit位为一个字节。
  点分十进制记法(可读性高)(129 11 11 239)
  十六进制记法(注册表、编程使用)(第一种:0x810B0BEF ,第二种:810B0BEF 16)

  为了符合人类的编程习惯,ip地址一般使用点分十进制来表示的,这是为了方便区分和记忆,但是由于计算机只认识0和1,所以在计算机中ip地址也是用二进制的0和1来表示,在编程中通常以十六进制来表示ip地址。由此可知,ip地址在不同使用场景下需要进行转换。另外,IPv4 地址本质上是 32 位无符号整数。

5. IPv4地址转换函数

  对于ip地址在网络中是以网络字节序形式传输的,有时候需要将点分十进制的ip地址转换成网络字节序的in_addr_t类型。下面这几个函数就是对ip地址进行淀粉十进制到in_addr_t类型之间的转换,在早期ip地址的转换函数只能转换IPv4的地址。

// 将点分十进制直接转换成 in_addr 类型(推荐使用)
int inet_aton(const char *cp, struct in_addr *inp);// 将点分十进制转换成 in_addr_t 类型,返回值保存的是网络字节序(不推荐使用)
in_addr_t inet_addr(const char *cp);// 将 in_addr 地址转换成点分十进制,返回点分十进制的ip地址。注意:这个函数是线程不安全的
char *inet_ntoa(struct in_addr in);

6. IPv4和IPv6地址转换函数

  下面使用的ip地址转换函数是随IPv6出现的新函数,对于IPv4和IPv6都支持,可以把ip地址转换转换成点分10进制来表示,比如:点分十进制记法表示129.11. 11.239,这样可读性就显得高很多了。

  inet_pton函数用来将点分十进制的ip地址转换为网络字节序,函数名中的p就表示点分十进制,n表示网络字节序

函数原型:

#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);  

参数说明:
  af:选择ip的版本(AF_INET代表ipv4,AF_INET6代表ipv6)
  src:源ip地址
  dst:转换后的目标ip地址是网络字节序(传出参数)

返回值:
  成功返回1,无效格式返回0,出错返回-1

inet_ntop函数用来将网络字节序转换为点分十进制的ip地址

函数原型:

#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);  

参数说明:
  af:选择ip的版本
  src:网络字节序的ip地址
  dst:存储转换后的字符串ip地址
  size:指定存储字符串ip地址的空间大小

返回值:
  成功返回ip地址(点分十进制形式的),出错则返回NULL

7. 通用的socketaddr数据结构

  linux早期是用sockaddr结构体来描述ipv4协议的,但是现在sockaddr结构体已经不推荐使用,因为历史原因,套接字函数函数早期在设计时是使用的struct sockaddr结构体,后期又设计了struct sockaddr_in来替代struct sockaddr,所以当在调用套接字函数声明传递参数的指针类型会存在问题,ANSI C标准提供了解决办法:将sockaddr定义成void *类型,也就是说sockaddr是一个通用的套接字地址结构。

通用的套接字地址结构,sockaddr结构体信息:

struct sockaddr {sa_family_t sa_family;  /* internet协议族, AF_xxx */char sa_data[14];       /*14字节的协议地址*/
};

  在使用struct sockaddr的时候需要进行强制转换成通用的套接字地址结构,即sockaddr结构:

//使用sockaddr_in定义
struct sockaddr_in addr;
//调用bind函数传参时需要对sockaddr_in类型强转成通用的sockaddr类型
bind((struct sockaddr *)&addr); 

8. 其他的套接字地址结构


图2-其他的套接字地址结构

sockaddr是早期用来表示IPv4地址的。

IPv4地址使用sockaddr_in结构体来表示,包括16位端口号,32为ip地址

IPv6地址用sockaddr_in6结构体表示,包括16位端口号、128位IP地址和一些控制字段

unix网络编程中是用sockaddr_un结构体表示,各种socket地址结构体的开头都是相同的,前16位表示整个结构体的长度,后16位表示地址类型。

IPv4、IPv6和Unix Domain Socket的地址类型分别定义为常数AF_INET、AF_INET6、AF_UNIX。

9. IPv4的sockaddr_in结构体

  IPv4地址用sockaddr_in结构体表示,包括16位端口号和32位IP地址,其中sin_addr成员的类型是一个in_addr结构体,该结构体中的s_addr成员就是用来存储ipv4的地址。

struct in_addr{in_addr_t s_addr   //ipv4地址
};struct sockaddr_in{short int sin_family;        //inernet地址族,如AF_INET(主机字节序)unsigned short int sin_port;  //端口号占16位(网络字节序)struct in_addr sin_addr;     //internet地址,32位ipv4地址(网络字节序)unsigned char sin_zero[8];   //以0填充(为了格式对齐的填充位)
}

  这样的话,只要取得某种sockaddr结构体的首地址,就可以根据地址类型字段确定结构体中的内容,因此我们在调用bind、accept、connect等套接字函数,应该将这些函数的参数都用通用的套接字地址struct sockaddr *类型表示,即在传递参数之前先强制转换成struct sockaddr *类型。

1-网络字节序和ip地址相关推荐

  1. 【Linux网络编程学习】预备知识(网络字节序、IP地址转换函数、sockaddr数据结构)

    此为牛客Linux C++课程和黑马Linux系统编程笔记. 1. 网络字节序 我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分. 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小 ...

  2. 网络字节序和IP地址详解

    文章目录 一.网络字节序 1.大端模式和小端模式 2.判断大端模式和小端模式 3.大端模式和小端模式相互转换 二.字节序转换函数 三.IP地址详解 1.IP地址的概念 2.IP地址的两种表示方法:整数 ...

  3. linux的基础知识——网络字节序转化,ip地址转换函数,sockaddr数据结构

    1.网络字节序 TCP/IP协议规定,网络数据流采用大端字节序,即低地址高字节.为了使网络程序具有可移植性,使得同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机 ...

  4. 本地字节序与网络字节序的相互转换(IP地址、端口号)

    一般数据在内存中是按照字节存储的,存储的方式分为大端和小端.在不知道对方主机的存储方式的情况下,我们不知道是否需要转换数据的存储方式.因此,TCP/IP协议规定:发送到网络的数据流应采用大端字节序! ...

  5. IP地址转换(字符串ip-整数,主机,网络字节序的转换)

    #include <arpa/inet.h>// p:点分十进制的IP字符串,n:表示network,网络字节序的整数int inet_pton(int af, const char *s ...

  6. IPv4地址的结构体与网络字节序

    IPv4地址的结构体 /* Fixed-size types, underlying types depend on word size and compiler. */ typedef signed ...

  7. 网络字节序与地址转换函数

    网络字节序是大端编码, 编码方式有两种: ①小端编码:高位数字存放在高地址字节中,如0x1234,小端编码机器将12存放在高位地址字节,34存放在低地址字节中,将其转化为1字节的char时,高地址字节 ...

  8. 网络:认识网络字节序

    IP地址和端口号 在IP数据报头中,有两个IP地址,分别是IP地址和目的IP地址: 端口号是传输层协议中的内容: 是一个2字节16位的整数: 用来标识进程,让当前的操作系统知道数据应该交给哪一个进程进 ...

  9. c语言主机字节序和网络字节序

    一.什么是字节序 字节序是指多字节数据在计算机内存中存储顺序,或者网络传输时各字节的传输顺序,字节序分为大端序和小端序. 大端序:高字节存储在低位地址,传输数据时高位在前: 小端序:低字节存储在低位地 ...

最新文章

  1. 深度学习七个实用技巧
  2. 01-sql优化及索引
  3. 怎么看python环境变量配置是否好了验证图片_python 的 tesserocr 模块安装与获取图片验证码...
  4. 完美解决NV4_disp.dll已正常停止工作”蓝屏问题
  5. bulter机器人_科普!九款使用率最高的物流机器人大盘点!
  6. 分布式服务框架Dubbo使用小结
  7. 如何使用CSS3 Border Radius属性
  8. Skywalking-03:Skywalking本地调试
  9. python续行_python 控制台单行刷新,多行刷新
  10. MVC之LayOut布局页
  11. Atitit order algo 排序算法 算法之道 目录 1.1. 生活中常用的排序是插入排序和选择排序 2 2. 0.1 算法分类 2 3. .2 算法复杂度 3 4. 十大经典排序算法(动图
  12. Excel数据透视表学习
  13. oracle sqlplus客户端,sqlplus下载|oracle sqlplus windows 客户端工具 64位下载 - 3322软件站...
  14. 【Pytorch-手写字体识别】手写字体识别项目
  15. 注册gitLab时报错There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.
  16. C语言新手记:相反数
  17. python k线形态识别_python量化金融系列-K线分析、及形态捕捉
  18. SUMIFS函数 、MATCH及INDEX函数
  19. javaweb项目实现连续3次输错密码后禁止登录
  20. 利用C语言实现大数加减法

热门文章

  1. 2月YouTube点赞Top10 :BTS防弹少年团回归屠榜!
  2. mysql mdl 锁_MySQL锁系列3 MDL锁
  3. echarts地图列表_ECharts中国地图选择器
  4. 电商如何借助小程序发力?
  5. vChain: Enabling Verifiable Boolean Range Queries over Blockchain Databases
  6. 如何在DXP中进行任何形状的敷铜?
  7. 芯片flash保护(解锁)
  8. Flash Builder 经典使用技巧
  9. windows10/11安全中心怎么关闭
  10. 鸿蒙系统硬盘分区,电脑硬盘分区分错了有哪些危害?如何正确分区?今天我再说一遍...