Linux网络:网络层-IP协议
IP协议
IP协议全称为"网际互连协议(Internet Protocol)",IP协议
是TCP/IP体系中的网络层协议
。
1、基本概念
网络层解决的问题
TCP
作为传输层控制协议,其保证的是
数据传输的可靠性
和传输效率
但TCP
仅仅是数据传输的策略
,而真正负责数据
在网络中传输
的则传输层之下的网络层
和链路层
。
- 双方在进行网络通信时,发送的数据并不是直接从一方的传输层直接发送到了另一方的传输层,而是需要
传输层将数据继续向下进行交付
,在网络层和链路层经过数据封装
后再通过网络发送到对方主机
。 - 对方主机收到数据后也同样需要在
链路层
和网络层
进行数据解包
,此时对方的传输层
才拿到了发送过来的数据,然后再继续将该数据向上进行交付
。
举例
:网络通信的过程,就像两个人在送互相送数据,这两个人分别在两栋楼的四楼,如果一个人要将数据交给对方,那么这个人就必须先从四楼走到一楼,然后再在路上经过路径选择到达对方楼下,最后再上到四楼将数据交给对方。

其中,送数据
的这个人从四楼下来
的过程就是数据封装
的过程,这个人在路上经过路径
选择到达对方楼下的过程就是数据路由的过程
,而这个人再上到四楼
将数据交给对方
的过程就是数据解包
的过程
- 而网络层要解决的问题就是,将数据从一台主机送到另一台主机,也就是数据的路由
保证数据可靠的从一台主机送到另一台主机的前提
说明一下:
- 网络层解决的问题是,将数据从一台主机送到另一台主机,因此网络层解决的是主机到主机的问题。
主机和路由器
- 主机:配有IP地址,但是不进行路由控制的设备
- 路由器:既配有IP地址,又能进行路由控制
- 节点:主机和路由器的统称
2、IP协议的格式
IP协议格式如下:

- 4位版本号(version):指定IP协议的版本(IPv4/IPv6),对于IPv4来说,就是4。
4位首部长度
(header length):表示IP报头的长度
,以4字节为单位16位总长度
(total length):IP报文(IP报头+有效载荷
)的总长度
,用于将各个IP报文进行分离。16位标识(id)
:唯一的标识主机发送的报文,如果数据在IP层进行了分片,那么每一个分片对应的id
都是相同的。3位标志字段
:第一位保留,表示暂时没有规定该字段的意义。第二位表示禁止分片,表示如果报文长度超过MTU,IP模块就会丢弃该报文。第三位表示"更多分片"
,如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。13位片偏移
(framegament offset):分片相对于原始数据开始处的偏移
- 8位协议:表示上层协议的类型。
32位源IP地址和32位目的IP地址
:表示发送端
和接收端
所对应的IP地址
IP如何将报头与有效载荷进行分离?
IP分离报头与有效载荷的方法与TCP是一模一样的,当IP从底层获取到一个报文后,虽然IP不知道报头的具体长度,但IP报文的前20个字节是IP的基本报头,并且这20字节当中涵盖4位首部长度。
因此IP是这样分离报头与有效载荷的:
- 当IP从底层获取到一个报文后,首先读取报文的前20个字节,并从中提取出4位的首部长度,此时便获得了IP报头的大小size
- 如果size的值大于20字节,则需要继续从报文当中读取size−20字节的数据,超过的这部分数据就是IP报头当中的选项字段
- 读取完IP的基本报头和选项字段后,剩下的就是有效载荷了。
IP就是通过这种"定长报头+自描述字段
"的方式进行报头和有效载荷的分离的。
32位源IP地址和32位目的IP地址
IP报头当中的32位源IP地址和32位目的IP地址,分别代表的就是该报文的发送端和接收端对应的IP地址。
理解socket编程:
- 在进行socket编程的时候,当一端想要发送数据给另一端时,必须要指明
对端的IP地址和端口号
,也就是发送数据的目的IP地址和目的端口号。 - 其中这里的IP地址就是给网络层的IP用的,用于数据在网络传输过程中的路由转发,而这里的端口号就是给传输层的TCP或UDP用的,用于指明该数据应该交给上层的哪一个进程。
- 发送数据时我们不需要指明发送数据的源IP地址和源端口号,因为传输层和网络层都是在操作系统内核当中实现的,数据在进行封装时操作系统会自行填充上对应的源IP地址和源端口号
8位生存时间
报文在网络传输过程中,可能因为某些原因
导致报文无法到达目标主机
,比如报文在路由时出现了环路路由的情况,或者目标主机已经异常离线了,此时这个报文就成了一个废弃的游离报文
。
为了避免
网络当中出现大量的游离报文
,于是在IP的报头当中就出现了一个字段,叫做8位生存时间
(Time To Live,TTL
)
8位生存时间
代表的是报文到达目的地的最大报文跳数
,每当报文经过一次路由,这里的生存时间就会减一,当生存时间减为0时该报文就会被自动丢弃,此时这个报文就会在网络中消散。
3、分片、组装
数据链路层解决的问题
IP能够将数据跨网络从一台主机送到另一台主机,而数据在进行跨网络传送时,需要经过一个个的路由器进行路由转发,最终才能到达目标主机。
比如要将数据从主机B跨网络传送到主机C,那么主机B需要先将数据交给路由器F,路由器F再将数据交给路由器G,...,最终由路由器D将数据交给主机C。

因此IP进行数据跨网络传送的前提是,需要先将数据从一个节点传送到和自己相连的下一个节点,这个问题实际就是由IP之下的数据链路层解决的,其中数据链路层最典型的代表协议就是MAC帧。
而两个节点直接相连也就意味着这两个节点是在同一个局域网当中的,因此要讨论两个相邻节点的数据传送时,实际讨论的就是局域网通信的问题。
最大传输单元
MTU=1500字节
MAC帧作为数据链路层的协议,它会将IP传下来的数据封装成数据帧,然后发送到网络当中。但MAC帧携带的有效载荷的最大长度是有限制的,也就是说IP交给MAC帧的报文不能超过某个值
,这个值就叫做最大传输单元
(Maximum Transmission Unit,MTU
),这个值的大小一般是1500字节
。
在Linux下使用ifconfig命令可以查看对应的MTU。

由于MAC帧无法发送大于1500字节的数据,因此IP层向下交付的数据的长度不能超过1500字节,这里所说的数据包括IP的报头和IP的有效载荷。
分片与组装
如果IP层
要传送的数据超过了1500字节
,那么就需要先在IP层对该数据进行分片
,然后再将分片后
的数据交给下层MAC帧
进行发送。

如果发送数据时在IP层进行了分片,那么当这些分片数据到达对端主机的IP层后就需要先进行组装,然后再将组装好的数据交付给上层传输层。
注意:
- 数据的
分片不是经常需要做的
,实际在网络通信过程中不分片才是常态,因为数据分片会存在一些潜在的问题,比如分片可能会增加丢包的概率
。 - 数据的
分片和组装
发生在IP层
,不仅源端主机可能会对数据进行分片,数据在路由过程中
的路由器也可能对数据进行分片
。因为不同网络的MTU是不一样的,如果传输路径上的某个网络的MTU比源端网络的MTU小,那么路由器就可能对IP数据报再次进行分片。 - 分片数据的
组装只会发生在目的端的IP层
- 在分片的数据中,每一个分片在IP层都会被添加上对应的IP报头,而传输层添加的报头只会出现在第一个分片中,因此网络中传输的数据包可能没有传输层的报头。
数据的分片和组装都是由IP层完成的
数据的分片和组装都是在IP层完成的,上层的传输层和下层的链路层并不关心
- 当TCP将待发送的数据交给IP后,TCP并不关心该数据是否会在IP层进行分片,即TCP并不关心数据具体的发送过程。(
因为TCP只是一种策略!
) - 当TCP从IP获取到数据后,TCP也不关心该数据是否在IP层经过了组装。
而链路层的MAC帧只负责
,将数据从一个节点传送到和自己相连的下一个节点。
- 当IP将待发送的数据交给MAC帧后,MAC帧并不知道该数据是IP经过分片后的某个分片数据,还是一个没有经过分片的数据,MAC帧只知道它一次最多只能发送MTU大小的数据,如果IP交给MAC帧大于MTU字节的数据,那MAC帧就无法进行发送。
- MAC帧从网络中获取到数据后,MAC帧也不关心这个数据是否需要进行组装,MAC帧只需要将该数据的MAC帧报头去掉后直接上交给上层IP就行了,而至于该数据的组装问题则是IP需要解决的。
因此,数据的分片和组装
完全是由IP协议自己完成
的,传输层和链路层不必关心也不需要关心。
分片的过程
假设IP层要发送4500字节的数据,由于该数据超过了MAC帧规定的MTU,因此IP需要先将该数据进行分片,然后再将一个个的分片交给MAC帧进行发送。
IP报头如果不携带选项字段,那么其大小就是20字节,假设IP层添加的IP报头的长度就是20字节,并按下列方式将数据分片后形成了四个分片报文:

需要注意的是,分片后的每一个分片数据都需要封装上对应的IP报头,因此4500字节的数据至少需要分为四个分片报文进行发送。
分片报文到达对方的IP层后需要被重新组装起来,因此IP层在对数据进行分片时需要记录分片的信息,而IP报头当中的16位标识
、3位标志
和13位片偏移
实际就是与数据分片相关的字段
。
- 16位标识:
唯一标识主机发送的报文
,如果数据在IP层进行了分片,那么每一个分片报文的16位标识是相同的。 - 3位标志:第一位保留,表示暂时没有规定该字段的意义。第二位表示禁止分片,表示如果报文长度超过MTU,IP模块就会丢弃该报文。
第三位表示"更多分片"
,如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。 - 13位片偏移:
分片相对于原始数据开始处的偏移
,表示当前分片在原数据中的偏移位置,实际偏移的字节数是这个值×8得到的。因此除了最后一个报文之外,其他报文的长度必须是8的整数倍,否则报文就不连续了。
因此上述四个分片报文对应的16位标识都是一样的,假设四个分片报文的16位标识都是123,则这四个报文对应的16位标识、3位标志中的"更多分片"和13位片偏移分别如下:


组装的过程
MAC帧交给IP层的数据可能来自世界各地,这些数据可能是经过分片后发送的,也可能是没有经过分片直接发送的,因此IP必须要通过某种方式来区分收到的各个数据。
对于各个分片报文来说:
- 第一个分片报文中的13位片偏移的值一定为0。
- 最后一个分片报文中的"更多分片"标志位一定为0
- 对于每一个分片报文来说,当前报文的13位片偏移加上当前报文的数据字节数÷ 8所得到的值,就是下一个分片报文的所对应的13位片偏移。
根据分片报文的这三个特点就能够将分片报文合理的组装起来。
为什么不建议进行分片?
虽然传输层并不关心IP层的分片问题,但分片对传输层也是有影响的。
需要注意的是,只要分片报文当中的某一个出现了丢包,此时传输层都需要将数据整体进行重传,因为传输层并不知道底层IP对数据进行了分片,当传输层发送出去的数据得不到应答时传输层就只能将数据整体进行重传,因此数据在发送时不建议进行分片。
如何尽可能避免分片?(
传输层向下交付数据时:少量多次
)
实际数据分片的根本原因在于传输层一次向下交付的数据太多了,导致IP无法直接将数据向下交给MAC帧,如果传输层控制好一次交给IP的数据量不要太大,那么数据在IP层自然也就不需要进行分片。
4、网段划分
IP地址的构成
IP地址由网络号和主机号两部分构成:
- 网络号:保证相互连接的
两个网段具有不同的标识。
- 主机号:同一网段内,
主机之间具有相同的网络号
,但是必须有不同的主机号。
可以在IP地址的后面加一个 /,并在 / 后面加上一个数字,这就表示从头数到第几位为止属于网络标识。
例如,下图中路由器连接了两个网段。对于网络标识来讲,同一网段内主机的网络标识是相同的,不同网段内主机的网络标识是不同的。而对于主机标识来讲,同一网段内主机的主机标识是不同的,不同网段内主机的主机标识是可以相同的。

- 不同的子网其实就是把网络号相同的主机放到一起。
- 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。
网段划分
过去曾经提出一种划分网络号和主机号的方案,就是把所有IP地址分为五类,如下图所示:

:

当要判断一个IP地址是属于哪一类时,只需要遍历IP地址的前五个比特位,第几个比特位最先出现0值,那么这个IP地址对应就属于A、B、C、D、E类地址
5、特殊的IP地址
并不是所有的IP地址都能够作为主机的IP地址,有些IP地址本身就是具有特殊用途的。
- 将IP地址中的
主机地址全部设为0
,就成为了网络号
,代表这个局域网
。 - 将IP地址中的
主机地址全部设为1
,就成为了广播地址
,用于给同一个链路
中相互连接的所有主机发送数据包
。 - 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1。
也就是说,IP地址中主机号为全0的代表的是当前局域网的网络号,IP地址中主机号为全1的代表的是广播地址,这两个IP地址都是不能作为主机的IP地址的。因此在某个局域网中最多能存在的主机个数是
6、IP地址的数量限制
IP地址数量不足问题
我们知道,IP地址(IPv4)是一个4字节32位的正整数,因此一共有2^32个IP地址,也就是将近43亿个IP地址。但TCP/IP协议规定,每个主机都需要有一个IP地址。
- 现在全世界人口已经有70多亿了,就算有一半的人没有智能手机,算下来也有30多亿台智能手机需要IP地址。
- 随着科技的发展,我们使用的电脑、智能手表、智能冰箱、智能洗衣机等设备如果要入网也是需要IP地址的。
- 另外,IP地址并不是按照主机台数来配置的,因此一个主机可能需要多个IP地址,更别谈还有很多组网的路由设备也需要IP地址,以及一些特殊的IP地址不能使用的问题。
如何解决IP地址不足问题
解决IP地址不足有以下几种方式:
动态分配IP地址
:只给接入网络的设备分配IP地址,因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的,避免了IP地址强绑定于某一台设备。NAT技术
:能够让不同局域网当中同时存在两个相同的IP地址,NAT技术不仅能解决IP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。IPv6
:IPv6用16字节128位来表示一个IP地址,能够大大缓解IP地址不足的问题。但IPv6并不是IPv4的简单升级版,它们是互不相干的两个协议,彼此并不兼容,因此目前IPv6还没有普及。
7、私网IP、公网IP
私网IP地址的种类
如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上使用任意的IP地址都可以,但是RFC 1918规定了用于组建局域网的私有IP地址
。
私有IP地址
只能有下面这三种情况:
- 10.*,前8位是网络号,共16,777,216个地址。
- 172.16.* 到172.31.*,前12位是网络号,共1,048,576个地址。
- 192.168.*,前16位是网络号,共65,536个地址。
包含在这个范围中的,都称为私网IP ,其余的则称为公网IP
(或全局IP)。

我们连接云服务器时,连接的这个IP地址就是云服务器的公网IP地址。

我们可以通过ifconfig命令来查看我们这台机器的私网IP,其中网络接口lo(loop)代表的是本地环回,而eth0代表的就是我这台机器的网络接口,可以看到我的私网IP地址是
需要注意的是,这里连接云服务器时的IP地址182.118.237.199,是云服务器的公网IP,由于我使用的是阿里云,因此这里的172.17.43.48是我这个云服务器在阿里内部的私网IP,可以看到这个IP正好在第二种私网IP范围内。
我们为什么要给运营商交钱?
我们享受的是互联网公司提供服务,但为什么需要向运营商交钱呢?
- 实际网络通信的基础设施都是
运营商搭建的基站
,我们访问服务器的数据并不是直接发送到了对应的服务器,而是需要经过运营商建设的各种基站以及各种路由器,最终数据才能到达对应的服务器 - 因为运营商为我们提供了通信的基础设施,所以我们交网费实际就相当于购买入网许可一样
- 没有运营商提供的这些基础设施,就不会诞生所谓的互联网公司,因为互联网公司是诞生在网络通信基础之上的。
也就是说,用户上网的数据首先必须经过运营商的相关网络设备,然后才能发送到互联网公司对应的服务器。因此所谓的网段划分、子网划分等工作实际都是运营商做的。
数据是如何发送到服务器的
路由器是连接两个或多个网络的硬件设备,在路由器上有两种网络接口,分别是LAN口和WAN口:
LAN口
(Local Area Network):表示连接本地网络的端口
,主要与家庭网络中的交换机、集线器或PC相连。WAN口
(Wide Area Network):表示连接广域网的端口
,一般指互联网。
我们将LAN口的IP地址叫做LAN口IP,也叫做子网IP,将WAN口的IP地址叫做WAN口IPO,也叫做外网IP。
我们使用的电脑、家用路由器、运营商路由器、广域网以及我们要访问的服务器之间的关系大致如下:

- 不同的路由器,子网IP其实都是一样的(通常都是192.168.1.1),子网内的主机IP地址不能重复,但是子网之间的IP地址就可以重复了。
- 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点,这样的运营商路由器可能会有很多级,最外层的运营商路由器的WAN口IP就是一个公网IP了。
- 如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有外网IP的服务器上,这样的服务器可以在阿里云/腾讯云上进行购买。

由于私网IP不能出现在公网当中
,因此子网内的主机在和外网进行通信时,路由器会不断将数据包IP首部中的源IP地址替换成路由器的WAN口IP,这样逐级替换,最终数据包中的源IP地址成为一个公网IP,这种技术成为NAT(Network Address Translation,网络地址转换)

为什么私网IP不能出现在公网当中?
- 不同的局域网中主机的IP地址可能是相同的,所以私网IP无法唯一标识一台主机,因此不能让私网IP出现在公网上,因为IP地址要能唯一标识公网上的一台主机。
- 但由于IP地址不足的原因,我们不能让主机直接使用公网IP而让主机使用私网IP,因为私网IP可以重复也就意味着我们可以在不同的局域网使用相同的IP地址,缓解了IP的不足。
两个局域网当中的主机不能不跨公网进行通信
- 两个局域网当中的主机理论上是不能不跨公网进行通信的,因为一个主机要将数据发送给另一台主机的前提是得先知道另一台主机的IP地址。
- 即便现在这个主机知道了另一台主机的IP地址,但有可能这两台主机的IP地址是一样的,因为它们的IP地址都是私网IP地址。
- 当这一台主机发送数据时将目的IP地址填成和自己相同的IP地址,操作系统就会认为这个数据就是要发给自己的,而不会向外进行发送了
所以数据要从一个局域网发送到另一个局域网,如果不经过公网是基本上不可能的
。我们在和别人聊天的时候,也不是直接将数据从一个局域网直接发送到了另一个局域网,而是先将数据经过公网发送到了服务器,然后再由服务器将数据经过公网转发到了另一个局域网。
但实际确实存在一些技术能够使数据包在发送过程中不进行公网IP的替换,而将数据正确送到目标主机,这种技术叫做内网穿透
,也叫做NAT穿透。
8、路由
数据"问路"的过程
数据在路由的过程中,实际就是一跳一跳(Hop by Hop)"问路"的过程。所谓"一跳"就是数据链路层中的一个区间,具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间。
IP数据包的传输过程中会遇到很多路由器,这些路由器会帮助数据包进行路由转发,每当数据包遇到一个路由器后,对应路由器都会查看该数据的目的IP地址,并告知该数据下一跳应该往哪跳。
路由表查询的具体过程
