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

-
其中,送数据的这个人从四楼下来的过程就是数据封装的过程,这个人在路上经过路径选择到达对方楼下的过程就是数据路由的过程,而这个人再上到四楼将数据交给对方的过程就是数据解包的过程。
-
而网络层要解决的问题就是,将数据从一台主机送到另一台主机,也就是数据的路由。
保证数据可靠的从一台主机送到另一台主机的前提
- 当双方在进行基于TCP的网络通信时,要保证将数据可靠的从一台主机送到另一台主机,前提是发送方要有将数据送到对方主机的能力,要是发送方连将数据发送给对方的能力都没有,那就更不用谈可靠的将数据送给对方主机了。
- 需要注意的是,发送方有将数据送到对方主机的能力,并不意味着发送方每次发送的数据都能够成功的发送到对方
- 一旦发送方有了将数据发送给对方的能力,就算发送方某次发送的数据没有成功到达对方,此时上层TCP由于没有收到对应数据的应答,此时上层TCP会要求进行数据重发,直到数据成功发送到对方主机为止。
- 也就是说,在网络层有能力将数据送到对方主机的情况下,虽然网络层不能保证每次都能将数据成功送到对方主机,但在TCP提供的可靠性策略的保证下,最终网络层就一定能够将数据可靠的发送到对方主机。
注:
- 网络层解决的问题是,将数据从一台主机送到另一台主机,因此网络层解决的是主机到主机的问题。
- 一方传输层从上方进程拿到数据后,该数据贯穿网络协议栈进行封装和解包,最终到达对方传输层,此时对方传输层也会将数据向上交给对应的进程,因此传输层解决的是进程到进程的问题。
路径选择
数据进行的网络传输一般都是跨网络的(局域网和公网),而路由器就是连接多个网络的硬件设备,因此数据在进行跨网络传输时一定需要经过多个路由器。

数据路由就像我们旅游一样,当确定了要到达的目标主机后,就需要寻找最优的路径到达该目的地。
- 确定数据路由的目的地后,数据就可以在网络中进行路由了,但数据在路由时无法自行进行路径选择,因为这个数据本身是"不认识路"的,因此数据在路由的过程中需要不断"找路人问路",而这里所谓的"路人"就是网络当中的一台台路由器。
- 网络当中的路由器是"认识路的",它们将自己的"认路经验"都记录到路由表当中,因此路由器可以通过查路由表找到去特定点的最优路径。因此数据在路由时,会不断通过路由器来进行路径选择,以此来一步步靠近目标网络或目标主机。

主机和路由器
- 主机:配有IP地址,但是不进行路由控制的设备。但实际现在几乎不存在不进行路由控制的设备了,就连你的笔记本也会进行路由控制。
- 路由器:既配有IP地址,又能进行路由控制。实际现在主流的路由器已经不仅仅具有路由的功能了,它甚至具备某些应用层的功能。
- 节点:主机和路由器的统称。
IP协议格式
IP协议格式如下:

-
4位版本号(version):指定IP协议的版本(IPv4/IPv6),对于IPv4来说,就是4
-
4位首部长度(header length):表示IP报头的长度,以4字节为单位。
-
8位服务类型(Type Of Service):3位优先权字段(已经弃用),4位TOS字段,和1位保留字段(必须置为0)。4位TOS分别表示:最小延时,最大吞吐量,最高可靠性,最小成本。这四者相互冲突,只能选择一个。比如对于ssh/telnet这样的应用程序,最小延时比较重要,而对于ftp这样的程序,最大吞吐量比较重要。
-
16位总长度(total length): IP数据报整体占多少个字节.
-
16位标识(id):唯一的标识主机发送的报文,如果数据在IP层进行了分片,那么每一个分片对应的id都是相同的。
-
3位标志字段:第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。第二位置为1表示禁止分片,这时候如果报文长度超过MTU, IP模块就会丢弃报文。第三位表示"更多分片",如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。
-
13位分片偏移(framegament offset):是分片相对于原始IP报文开始处的偏移.其实就是在表示当前分片在原报文中处在哪个位置.实际偏移的字节数是这个值* 8得到的.因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了).
-
8位生存时间(Time To Live,TTL):数据报到达目的地的最大报文跳数,一般是64,每经过一个路由,TTL -= 1,一直减到0还没到达,那么就丢弃了,这个字段主要是用来防止出现路由循环。
-
8位协议:表示上层协议的类型
-
16位首部检验和:使用CRC进行校验,来鉴别数据报的首部是否损坏,但不检验数据部分。
-
32位源地址和32位目标地址:表示发送端和接收端.
-
选项字段:不定长,最多40字节。
IP报头在内核当中本质就是一个位段类型,给数据封装IP报头时,实际上就是用该位段类型定义一个变量,然后填充IP报头当中的各个属性字段,最后将这个IP报头拷贝到数据的首部,至此便完成了IP报头的封装。
IP如何将报头与有效载荷进行分离?
IP分离报头与有效载荷的方法与TCP是一模一样的,当IP从底层获取到一个报文后,虽然IP不知道报头的具体长度,但IP报文的前20个字节是IP的基本报头,并且这20字节当中涵盖4位首部长度。
- 当IP从底层获取到一个报文后,首先读取报文的前20个字节,并从中提取出4位的首部长度,此时便获得了IP报头的大小size。
- 如果size的值大于20字节,则需要继续从报文当中读取size−20字节的数据,这部分数据就是IP报头当中的选项字段。
- 读取完IP的基本报头和选项字段后,剩下的就是有效载荷了。
-
IP就是通过这种"定长报头+自描述字段"的方式进行报头和有效载荷的分离的。但需要注意的是,IP报头当中的4位首部长度描述的基本单位与TCP报头当中的4位首部长度一样,都是以4字节为单位进行描述的,这也恰好是报文的宽度。
-
4位二进制的取值范围是0000 ~ 1111,因此IP报头的最大长度为15 × 4 = 60字节,因为基本报头的长度是20字节,所以IP报头中选项字段的长度最多是40字节。如果IP报头当中不携带选项字段,那么IP报头的长度就是20字节,此时报头当中的4位首部长度字段所填的值就是20 ÷ 4 = 5 ,即0101。
IP如何决定将有效载荷交付给上层的哪一个协议?
基于IP协议的传输层协议不止一种,因此当IP从底层获取到一个报文并对其进行解包后,IP需要知道应该将分离后得到的有效载荷交付给上层的哪一个协议。
在IP报头当中有一个字段叫做8位协议,该字段表示的就是上层协议的类型,IP就是根据该字段判定应该将分离出来的有效载荷交付给上层的哪一个协议的。该字段是发送方的IP层从上层传输层获取到数据后填充的,比如是上层TCP交给IP层的数据,那么该数据在封装IP报头时的8位协议填充的就是TCP对应的编号。
32位源IP地址和32位目的IP地址
IP报头当中的32位源IP地址和32位目的IP地址,分别代表的就是该报文的发送端和接收端对应的IP地址。
当接收端收到了发送端发来的数据后,接收端可能也想要给发送端发送数据,因此发送端在发送数据时除了需要指明该数据的目的IP地址,还需要指明该数据的源IP地址,也就是发送端的IP地址。即便接收端收到数据后没有数据想要发送给发送端,但至少接收端需要向发送端发送一个响应报文,表明发送端发送的数据已经被接收端可靠的收到了,因此发送出去的数据除了需要指明该数据的目的IP地址,还需要指明该数据的源IP地址。
理解socket编程:
- 在进行socket编程的时候,当一端想要发送数据给另一端时,必须要指明对端的IP地址和端口号,也就是发送数据的目的IP地址和目的端口号。
- 其中这里的IP地址就是给网络层的IP用的,用于数据在网络传输过程中的路由转发,而这里的端口号就是给传输层的TCP或UDP用的,用于指明该数据应该交给上层的哪一个进程。
- 发送数据时我们不需要指明发送数据的源IP地址和源端口号,因为传输层和网络层都是在操作系统内核当中实现的,数据在进行封装时操作系统会自行填充上对应的源IP地址和源端口号。
8位生存时间
报文在网络传输过程中,可能因为某些原因导致报文无法到达目标主机,比如报文在路由时出现了环路路由的情况,或者目标主机已经异常离线了,此时这个报文就成了一个废弃的游离报文。
为了避免网络当中出现大量的游离报文,于是在IP的报头当中就出现了一个字段,叫做8位生存时间(Time To Live,TTL)。8位生存时间代表的是报文到达目的地的最大报文跳数,每当报文经过一次路由,这里的生存时间就会减一,当生存时间减为0时该报文就会被自动丢弃,此时这个报文就会被丢弃。
分片与组装
数据链路层解决的问题
IP能够将数据跨网络从一台主机送到另一台主机,而数据在进行跨网络传送时,需要经过一个个的路由器进行路由转发,最终才能到达目标主机。
比如要将数据从主机B跨网络传送到主机C,那么主机B需要先将数据交给路由器F,路由器F再将数据交给路由器G,...,最终由路由器D将数据交给主机C。

-
因此IP进行数据跨网络传送的前提是,需要先将数据从一个节点传送到和自己相连的下一个节点,这个问题实际就是由IP之下的数据链路层解决的,其中数据链路层最典型的代表协议就是MAC帧。
-
而两个节点直接相连也就意味着这两个节点是在同一个局域网当中的,因此要讨论两个相邻节点的数据传送时,实际讨论的就是局域网通信的问题。
最大传输单元 MTU
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协议可以组织进行数据重传。
- 当TCP将待发送的数据交给IP后,TCP并不关心该数据是否会在IP层进行分片,即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报头字节数 | 有效载荷字节数 |
---|---|---|---|
1 | 1500 | 20 | 1480 |
2 | 1500 | 20 | 1480 |
3 | 1500 | 20 | 1480 |
4 | 80 | 20 | 60 |
需要注意的是,分片后的每一个分片数据都需要封装上对应的IP报头,因此4500字节的数据至少需要分为四个分片报文进行发送。
- 分片报文到达对方的IP层后需要被重新组装起来,因此IP层在对数据进行分片时需要记录分片的信息,而IP报头当中的16位标识、3位标志和13位片偏移实际就是与数据分片相关的字段。
- 16位标识:唯一标识主机发送的报文,如果数据在IP层进行了分片,那么每一个分片报文的16位标识是相同的。
- 3位标志:第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到).第二位置为1表示禁止分片,这时候如果报文长度超过MTU, IP模块就会丢弃报文。第三位表示"更多分片",如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。
- 13位片偏移:分片相对于原始数据开始处的偏移,表示当前分片在原数据中的偏移位置,实际偏移的字节数是这个值*8得到的。因此除了最后一个报文之外,其他报文的长度必须是8的整数倍,否则报文就不连续了。
因此上述四个分片报文对应的16位标识都是一样的,假设四个分片报文的16位标识都是0x1234,则这四个报文对应的16位标识、3位标志中的"更多分片"和13位片偏移分别如下:
分片报文 | 总字节数 | IP报头字节数 | 数据字节数 | 16位标识 | "更多分片" | 13位片偏移 |
---|---|---|---|---|---|---|
1 | 1500 | 20 | 1480 | 0x1234 | 1 | 0 |
2 | 1500 | 20 | 1480 | 0x1234 | 1 | 185 |
3 | 1500 | 20 | 1480 | 0x1234 | 1 | 370 |
4 | 80 | 20 | 60 | 0x1234 | 0 | 555 |
需要注意的是,13位片偏移当中记录的字节数是当前分片在原数据开始处的偏移字节数的值÷ 8得到的,比如分片报文2在原始数据开始处的偏移字节数是1480,其对应的13位片偏移的值就是1480 ÷ 8 = 185 。
组装的过程
MAC帧交给IP层的数据可能来自世界各地,这些数据可能是经过分片后发送的,也可能是没有经过分片直接发送的,因此IP必须要通过某种方式来区分收到的各个数据。
- IP报头当中有32位源IP地址,源IP地址记录了发送端所对应的IP地址,因此通过IP报头当中的32位源IP地址就可以区分来自不同主机的数据。
- IP报头当中有16位标识,未分片的数据各自的16位标识都是不同的,而由同一个数据分片得到的各个分片报文所对应的16位标识都是相同的,因此通过IP报头当中16位标识就可以判断哪些报文是没有经过分片的独立报文,哪些报文是经过分片后的分片报文。
因此IP可以通过IP报头当中的32位源IP地址和16位标识,将经过分片的数据各自聚合在一起,聚合在一起后就可以开始进行组装了。
对于各个分片报文来说:
- 第一个分片报文中的13位片偏移的值一定为0,且更多分片的标志位为1。
- 最后一个分片报文中的"更多分片"标志位一定为0,分片报文中的13位片偏移的值一定不为0。
- 对于每一个分片报文来说,当前报文的13位片偏移加上当前报文的数据字节数 ÷ \div÷ 8所得到的值,就是下一个分片报文的所对应的13位片偏移。
根据分片报文的这三个特点就能够将分片报文合理的组装起来。
- 先找到分片报文中13位片偏移为0的分片报文,然后提取出其IP报头当中的16位总长度字段,通过计算即可得出下一个分片报文所对应的13位片偏移,按照此方式依次将各个分片报文拼接起来。
- 直到拼接到一个"更多分片"标志位为0的分片报文,此时表明分片报文组装完毕。
分片报文丢包的问题
分片后的报文在网络传输过程中也可能会出现丢包问题,但接收端有能力判断是否收到了全部分片报文,比如假设某组分片报文对应的16位标识值为x:
- 如果分片报文中的第一个分片报文丢包了,那么接收端收到的分片报文中就找不到对应16位标识为x,并且13位片偏移为0的分片报文。
- 如果分片报文中的最后一个分片报文丢包了,那么接收端收到的分片报文中就找不到对应16为标识为x,并且"更多分片"标志位为0的分片报文。
- 如果分片报文中的其它分片报文丢包了,那么接收端在进行分片报文的组装时就会发现偏移值不连续。(找不到对应13位片偏移为特定值的分片报文)
注:
需要注意的是,未分片报文的"更多分片"标志位为0,最后一个分片报文的"更多分片"标志位也为0,但当接收端只收到分片报文中的最后一个分片报文时,接收端不会将其识别成一个未分片的报文,因为未分片的报文所对应的13位片偏移的值也应该是0,而最后一个分片报文所对应的13位片偏移的值不为0。
为什么不建议进行分片?
虽然传输层并不关心IP层的分片问题,但分片对传输层也是有影响的。
- 如果一个数据在网络传输过程中没有经过分片,那么只要接收端收到了这一个报文,我们就可以认为该数据被对方可靠的收到了。
- 而如果一个数据在网络传输过程中进行了分片,那么只有当接收端收到了全部的分片报文并将其成功组装起来,这时我们才认为该数据被对方可靠的收到了。但如果众多的分片报文当中有一个报文出现了丢包,就会导致接收端就无法将报文成功组装起来,这时接收端会将收到的分片报文全部丢弃,此时传输层TCP会因为收不到对方应答而进行超时重传。
- 假设在网络传输时丢包的概率是万分之一,如果将数据拆分为一百份进行发送,那么此时丢包的概率就上升到了百分之一。因为只要有一个分片报文丢包了也就等同于这个报文整体丢失了,因此分片会增加传输层重传数据的概率。
需要注意的是,只要分片报文当中的某一个出现了丢包,此时传输层都需要将数据整体进行重传,因为传输层并不知道底层IP对数据进行了分片,当传输层发送出去的数据得不到应答时传输层就只能将数据整体进行重传,因此数据在发送时不建议进行分片。
如何尽可能避免分片?
实际数据分片的根本原因在于传输层一次向下交付的数据太多了,导致IP无法直接将数据向下交给MAC帧,如果传输层控制好一次交给IP的数据量不要太大,那么数据在IP层自然也就不需要进行分片。
- 因此TCP作为传输控制协议,它需要控制一次向下交付数据不能超过某一阈值,这个阈值就叫做MSS(Maximum Segment Size,最大有效载荷长度)。
- 通信双方在建立TCP连接时,除了需要协商自身窗口大小等概念之外,还会协商后续通信时每一个报文段所能承载的最大报文段长度MSS。
MAC帧的有效载荷最大为MTU(Maximum Transmission Unit),TCP的有效载荷最大为MSS,由于TCP和IP常规情况下报头的长度都是20字节,因此一般情况下 MSS = MTU - 20 - 20,而MTU的值一般是1500字节,因此MSS的值一般就是1460字节。
所以一般建议TCP将发送的数据控制在1460字节以内,此时就能够降低数据分片的可能性。之所以说是降低数据分片的可能性,是因为每个网络的链路层对应的MTU可能是不同的,如果数据在传输过程中进入到了一个MTU较小的网络,那么该数据仍然可能需要在路由器中进行分片。
网段划分
IP地址分为两个部分,网络号和主机号
- 网络号:保证相互连接的两个网段具有不同的标识。
- 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号。

- 路由器的网段标识一般是(网络标识.主机标识,主机标识固定为1)
- 不同的子网其实就是把网络号相同的主机放到一起。
- 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。
- 通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同.
DHCP协议
实际手动管理IP地址是一个非常麻烦的事情,当子网中新增主机时需要给其分配一个IP地址,当子网当中有主机断开网络时又需要将其IP地址进行回收,便于分配给后续新增的主机使用。
- 有一种技术叫做DHCP,能够自动的给子网内新增主机节点分配IP地址,避免了手动管理IP的不便.
- 一般的路由器都带有DHCP功能.因此路由器也可以看做一个DHCP服务器.
DHCP(Dynamic Host Configuration Protocol)是一种用于自动分配网络配置信息的网络协议。在Linux和其他操作系统中,DHCP协议用于配置计算机、移动设备和其他网络设备的IP地址、子网掩码、默认网关、DNS服务器等网络参数。
DHCP协议的工作原理如下:
客户端请求:当计算机或设备连接到一个网络时,它通常会在启动时发送一个DHCP请求。这个请求被广播到网络中的DHCP服务器。
DHCP服务器响应:DHCP服务器接收到客户端的请求后,会向客户端发送DHCP响应。这个响应包含了分配给客户端的IP地址以及其他网络配置参数,如子网掩码、默认网关、DNS服务器等。
IP地址租约:DHCP服务器通常会为分配给客户端的IP地址分配一个租约期限,客户端在租约期限内可以使用该IP地址。一旦租约到期,客户端必须续租或请求新的租约。
DHCP协议的主要优点包括:
自动化:DHCP协议使网络配置自动化,减少了手动配置的需要。这对大型网络和企业网络特别有用,因为它可以减轻管理员的工作负担。
IP地址管理:DHCP服务器可以分配和管理IP地址,确保不会出现IP地址冲突。
灵活性:DHCP允许网络管理员为不同的客户端分配不同的网络配置参数,以满足其需求。
IP地址重用:DHCP服务器可以为不再使用的IP地址分配给其他设备,提高了IP地址的有效利用。
在Linux中,您可以设置Linux系统以作为DHCP服务器或DHCP客户端运行,或者配置Linux系统以接受来自其他DHCP服务器的配置信息。DHCP客户端通常在Linux系统上默认启用,以获取来自网络上的DHCP服务器的IP地址和其他配置信息。
如果您希望在Linux系统上设置DHCP服务器,可以使用DHCP服务器软件,如ISC DHCP Server,来分配IP地址和其他网络配置。
先找目标网络,再找目标主机
当IP要将数据跨网络从一台主机发送到另一台主机时,其实不是直接将数据发送到了目标主机,而是先将数据发送到目标主机所在的网络,然后再将数据发送到目标主机。
因此数据在路由时的第一目的并不是找到目标主机,而是找到目标网络所在的网络,然后再在目标网络当中找到目标主机。
数据路由时之所以不一开始就以找目标主机为目的,因为这样效率太低了。
- 找主机的过程本质是排除的过程,如果一开始就以找目标主机为目的,那么在查找的过程中一次只能排除一个主机。
- 而如果一开始先以找目标网络为目的,那么在查找过程中就能一次排除大量和目标主机不在同一网段的主机,这样就可以大大提高检索的效率。
因此,为了提高数据路由的效率,我们对网络进行了网段划分。
网段划分
过去曾经提出一种划分网络号和主机号的方案,把所有IP地址分为五类,如下图所示(该图出自[TCPIP])。

因此,各类IP地址的取值范围如下:
- A类:0.0.0.0到127.255.255.255。
- B类:128.0.0.0到191.255.255.255。
- C类:192.0.0.0到223.255.255.255。
- D类:224.0.0.0到239.255.255.255。
- E类:240.0.0.0到247.255.255.255。
当要判断一个IP地址是属于哪一类时,只需要遍历IP地址的前五个比特位。
子网划分
随着Internet的飞速发展,这种划分方案的局限性很快显现出来,大多数组织都申请B类网络地址,导致B类地址很快就分配完了,而A类却浪费了大量地址;
- 例如,申请了一个B类地址,理论上一个子网内能允许6万5千多个主机. A类地址的子网内的主机数更多.
- 然而实际网络架设中,不会存在一个子网内有这么多的情况.因此大量的IP地址都被浪费掉了.
针对这种情况提出了新的划分方案,称为CIDR(Classless Interdomain Routing):
- 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号;
- 子网掩码也是一个32位的正整数.通常用一串"0"来结尾;
- 将IP地址和子网掩码进行"按位与"操作,得到的结果就是网络号;
- 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关;
在Linux中,CIDR(Classless Inter-Domain Routing,无类域间路由)是一种网络标记和分配IP地址的方法,用于更有效地分配IP地址和管理网络路由。CIDR取代了早期的IP地址分配方案,如类A、类B和类C地址,使网络管理员能够更灵活地管理IP地址资源。
理解CIDR的关键概念包括:
IP地址:IP地址是用于在互联网上标识计算机和设备的唯一地址。IPv4地址通常以四个十进制数(例如,192.168.1.1)表示,每个数的范围从0到255。IPv6地址使用更长的十六进制值。
子网掩码:子网掩码是用于确定IP地址中哪部分用于网络标识,哪部分用于主机标识的掩码。它由一系列1和0组成,其中1表示网络标识部分,0表示主机标识部分。例如,IPv4的常见子网掩码是255.255.255.0,或使用CIDR表示为/24。
CIDR表示法:CIDR使用斜杠后跟一个数字,表示子网掩码的位数。例如,/24表示子网掩码为255.255.255.0,或者表示IP地址的前24位用于网络标识,剩余的位用于主机标识。
地址块:CIDR表示法允许将一系列IP地址组合成一个地址块,使它们可以一起分配或路由。例如,192.168.1.0/24表示包括192.168.1.0到192.168.1.255之间的所有地址。
无类别路由:CIDR是无类别路由的一部分,它意味着不再需要依赖早期的类别A、类别B、类别C等IP地址分配,而可以根据需要创建更灵活的自定义子网。
理解CIDR对于网络管理员来说非常重要,因为它允许更精确地规划和分配IP地址,减少浪费,提高网络效率,以及更好地管理路由表。在Linux中,您可以使用CIDR表示法来配置子网、路由和防火墙规则等,以更好地管理和保护您的网络。
下面,举两个例子:
划分子网的例子1:

划分子网的例子2:

- 可见,IP地址与子网掩码做与运算可以得到网络号,主机号从全0到全1就是子网的地址范围;
- IP地址和子网掩码还有一种更简洁的表示方法,例如140.252.20.68/24,表示IP地址为140.252.20.68,子网掩码的高24位是1,也就是255.255.255.0
特殊的IP地址
并不是所有的IP地址都能够作为主机的IP地址,有些IP地址本身就是具有特殊用途的。
- 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网;
- 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包;
- 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1
也就是说,IP地址中主机号为全0的代表的是当前局域网的网络号,IP地址中主机号为全1的代表的是广播地址,这两个IP地址都是不能作为主机的IP地址的。因此在某个局域网中最多能存在的主机个数是2^(主机号位数)-2。
本机环回基本原理
在Linux中,"loopback" 设备是一个特殊的虚拟网络接口,通常标识为lo
。这个设备用于本地主机(即您的计算机)内部的网络通信,而不经过物理网络。它是一种非常有用的工具,用于本地主机上的网络测试、诊断和通信。以下是 loopback 设备的一些关键特点和用途:
IP地址:Loopback 设备具有特殊的IP地址,通常是 127.0.0.1,这个IP地址通常被称为 "localhost" 或 "loopback地址"。您可以使用这个地址来引用本地主机上运行的服务和应用程序。
本地回环:当您向本地回环接口发送数据包时,这些数据包实际上不离开您的计算机,而是被传送到 loopback 设备上,并被相应的应用程序接收。这使得您可以测试和调试网络服务,而无需实际连接到网络。
本地通信:本地主机上运行的不同应用程序可以通过 loopback 设备进行通信。这对于分割的应用程序组件之间的通信非常有用,而不需要经过网络协议栈。
网络诊断:Loopback 设备还可用于网络诊断工具,如Ping,以测试网络协议栈的功能和连接。
环回接口是必需的:对于大多数Linux系统,loopback 设备是网络栈的一部分,并且在启动时默认启用。它通常会有一个固定的IP地址(127.0.0.1),而无需手动配置。
总之,loopback 设备是Linux中的一个重要网络工具,用于本地主机上的网络通信、测试和诊断。它允许本地主机上的不同应用程序之间进行高效的通信,同时不经过物理网络。这对于开发和调试网络服务以及确保网络协议栈正常运行非常有用。
本机环回会将数据贯穿网络协议栈,但最终并不会将数据发送到网络当中,相当于本机环回时不会将数据写到网卡上面。
本机环回的目的就是将数据自顶向下贯穿协议栈,进行一次数据封装的过程,然后再自底向上贯穿协议栈,进行一次数据的解包和分用,用于测试本地的网络功能是否正常。
本机环回的基本原理:
- 当数据到达IP层需要继续向下交付时,如果是环回程序,那么IP输出函数会将该数据放入到IP输入队列当中,然后再由IP输入函数读取上去。
- 而IP输入函数将数据读取上去的本应该是链路层交付上来的数据,因此该数据后续就会被当作从网络中读取上来的数据看待,各层协议会对该数据依次进行解包和分用。
- 如果不是环回程序的话,那么接下来就会判断该数据对应的目的IP地址是否为广播或多播地址,或者目的IP地址是否与本主机的IP地址相同,如果是则也会将该数据放入到IP输入队列当中,等待IP输入函数将其读走。
- 只有判断程序不是环回程序,并且也不是广播或多播,或发给本主机的数据后(IP层面上),就是说此时本主机要将数据发送给同一网段其他IP的主机,那么就使用ARP广播获取该数据目的主机的以太网地址(MAC地址)并进行后续数据发送的操作。注:比如A192.24.25.23和B 192.24.25.32 同一网段,要单播通信也是需要A进行ARP广播,B收到广播后 把自己的MAC会给到A;之后A收到保存在ARP缓存中,通讯开始;

IP地址的数量限制
- 我们知道, IP地址(IPv4)是一个4字节32位的正整数.那么一共只有2的32次方个IP地址,大概是43亿左右.而TCP/IP协议规定,每个主机都需要有一个IP地址.这意味着,一共只有43亿台主机能接入网络么?
- 实际上,由于一些特殊的IP地址的存在,数量远不足43亿;另外IP地址并非是按照主机台数来配置的,而是每一个网卡都需要配置一个或多个IP地址.
- CIDR在一定程度上缓解了IP地址不够用的问题(提高了利用率,减少了浪费,但是IP地址的绝对上限并没有增加),仍然不是很够用.这时候有三种方式来解决:
- 动态分配IP地址:只给接入网络的设备分配IP地址.因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的;
- NAT技术(后面会重点介绍);
- IPv6: IPv6并不是IPv4的简单升级版.这是互不相干的两个协议,彼此并不兼容; IPv6用16字节128位来表示一个IP地址;但是目前IPv6还没有普及;
私网IP地址和公网IP地址
如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上使用任意的IP地址都可以,但是RFC 1918规定了用于组建局域网的私有IP地址
- 10.*,前8位是网络号,共16,777,216个地址。
- 172.16.到172.31.,前12位是网络号,共1,048,576个地址。
- 192.168.*,前16位是网络号,共65,536个地址。
包含在这个范围中的,都称为私网IP,其余的则称为公网IP(或全局IP)。
我们连接云服务器时,连接的这个IP地址就是云服务器的公网IP地址。

我们可以通过curl ifconfig.me
命令来查看我们这台机器对应的公网IP,使用ifconfig
命令来查看我们这台机器的私网IP,其中网络接口lo(loop)代表的是本地环回,而eth0代表的就是我这台机器的网络接口,可以看到我的私网IP地址是10.0.4.17。
需要注意的是,这里连接云服务器时的IP地址49.232.66.206,是云服务器的公网IP,由于我使用的是腾讯云,因此这里的10.0.4.17是我这个云服务器在腾讯内部的私网IP,可以看到这个IP正好在第一种私网IP(10.*)范围内。
我们为什么要给运营商交钱?
我们享受的是互联网公司提供服务,但为什么需要向运营商交钱呢?
- 实际网络通信的基础设施都是运营商搭建的,我们访问服务器的数据并不是直接发送到了对应的服务器,而是需要经过运营商建设的各种基站以及各种路由器,最终数据才能到达对应的服务器。
- 因为运营商为我们提供了通信的基础设施,所以我们交网费实际就相当于购买入网许可一样。
- 没有运营商提供的这些基础设施,就不会诞生所谓的互联网公司,因为互联网公司是诞生在网络通信基础之上的。
- 也就是说,用户上网的数据首先必须经过运营商的相关网络设备,然后才能发送到互联网公司对应的服务器。因此所谓的网段划分、子网划分等工作实际都是运营商做的。
数据是如何发送到服务器的
路由器是连接两个或多个网络的硬件设备,在路由器上有两种网络接口,分别是LAN口和WAN口:
WAN口IP(Wide Area Network Interface IP)和LAN口IP(Local Area Network Interface IP)是两种不同的IP地址,通常在路由器或网络设备上使用,用于区分设备在广域网络(WAN)和本地局域网络(LAN)之间的不同网络接口。
以下是它们的主要区别:
WAN口IP:
位置:WAN口IP地址通常分配给网络设备的广域网接口,用于与互联网上的其他设备和网络通信。这是设备与互联网提供商(ISP)之间的接口。
可见性:WAN口IP地址是可见于互联网的,因为它是设备与外部互联网之间的连接点。这个IP地址通常由ISP分配。
全局唯一性:WAN口IP地址是全球唯一的,因为它必须在全球范围内唯一标识设备,以便在互联网上进行通信。
公网IP:通常,WAN口IP地址是公网IP地址,可以用于直接访问互联网。
LAN口IP:
位置:LAN口IP地址分配给网络设备的本地局域网接口,用于在局域网络内部的设备之间进行通信。这是设备与本地网络中其他设备的接口。
可见性:LAN口IP地址通常不可见于互联网,因为它们是用于内部局域网络通信的。通常,这些IP地址是私网IP地址。
范围:LAN口IP地址通常在特定的私网IP地址范围内,如IPv4中的10.0.0.0/8、172.16.0.0/12 和 192.168.0.0/16。
内部通信:LAN口IP地址用于设备在局域网络内部相互通信,而不是与互联网上的设备进行通信。
总之,WAN口IP地址用于设备与互联网之间的通信,而LAN口IP地址用于设备在局域网络内部的通信。它们通常位于不同的子网中,以区分内部通信和外部通信,以及局域网络和广域网络之间的通信。
我们将LAN口的IP地址叫做LAN口IP,也叫做子网IP,将WAN口的IP地址叫做WAN口IPO,也叫做外网IP。
我们使用的电脑、家用路由器、运营商路由器、广域网以及我们要访问的服务器之间的关系大致如下:

- 一个路由器可以配置两个IP地址,一个是WAN口IP,一个是LAN口IP(子网IP).
- 路由器LAN口连接的主机,都从属于当前这个路由器的子网中.
- 不同的路由器,子网IP其实都是一样的(通常都是192.168.1.1).子网内的主机IP地址不能重复.但是子网之间的IP地址就可以重复了.
- 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点.这样的运营商路由器可能会有很多级,最外层的运营商路由器, WAN口IP就是一个公网IP了.
- 子网内的主机需要和外网进行通信时,路由器将IP首部中的IP地址进行替换(替换成WAN口IP),这样逐级替换,最终数据包中的IP地址成为一个公网IP.这种技术称为NAT(Network Address Translation,网络地址转换).
- 如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有外网IP的服务器上.这样的服务器可以在阿里云/腾讯云上进行购买.
为什么私网IP不能出现在公网当中?
- 不同的局域网中主机的IP地址可能是相同的(IP地址要能唯一标识公网上的一台主机),所以私网IP无法唯一标识一台主机,因此不能让私网IP出现在公网上。
- 但由于IP地址不足的原因,我们不能让主机直接使用公网IP而让主机使用私网IP,因为私网IP可以重复也就意味着我们可以在不同的局域网使用相同的IP地址,缓解了IP的不足。
路由
在复杂的网络结构中,找出一条通往终点的路线;
路由的过程,就是这样一跳一跳(Hop by Hop) "问路"的过程.
所谓"一跳"就是数据链路层中的一个区间.具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间.

IP数据包的传输过程也和问路一样.
- 当IP数据包,到达路由器时,路由器会先查看目的IP;
- 路由器决定这个数据包是能直接发送给目标主机,还是需要发送给下一个路由器;
- 依次反复,一直到达目标IP地址;
那么如何判定当前这个数据包该发送到哪里呢?这个就依靠每个节点内部维护一个路由表;

路由表查询的具体过程
- 路由表可以使用route命令查看

- 如果目的IP命中了路由表,就直接转发即可;
- 路由表中的最后一行,主要由下一跳地址和发送接口两部分组成,当目的地址与路由表中其它行都不匹配时,就按缺省路由条目规定的接口发送到下一跳地址。
假设某主机上的网络接口配置和路由表如下:

-
这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到192.168.56.0/24网络;
-
路由表的Destination是目的网络地址,Genmask是子网掩码,Gateway是下一跳地址,Iface是发送接口
-
Flags中的U标志表示此条目有效(可以禁用某些条目),G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络(属于同一个子网,可以不通过路由器,直接由A主机发送给B主机),不必经路由器转发;
转发过程例1:如果要发送的数据包的目的地址是192.168.56.3
- 跟第一行的子网掩码做与运算得到192.168.56.0,与第一行的目的网络地址不符
- 再跟第二行的子网掩码做与运算得到192.168.56.0,正是第二行的目的网络地址,因此从eth1接口发送出去;
- 由于192.168.56.0/24正是与eth1接口直接相连的网络,因此可以直接发到目的主机,不需要经路由器转发;
转发过程例2:如果要发送的数据包的目的地址是202.10.1.2
- 依次和路由表前几项进行对比,发现都不匹配;
- 按缺省路由条目,从eth0接口发出去,发往192.168.10.1路由器;
- 由192.168.10.1路由器根据它的路由表决定下一跳地址;
路由表生成算法
路由可分为静态路由和动态路由:
- 静态路由:是指由网络管理员手工配置路由信息。
- 动态路由:是指路由器能够通过算法自动建立自己的路由表,并且能够根据实际情况进行调整。
路由表相关生成算法:距离向量算法、LS算法、Dijkstra算法等。
的条目表示目的网络地址是与本机接口直接相连的网络(属于同一个子网,可以不通过路由器,直接由A主机发送给B主机),不必经路由器转发;
转发过程例1:如果要发送的数据包的目的地址是192.168.56.3
- 跟第一行的子网掩码做与运算得到192.168.56.0,与第一行的目的网络地址不符
- 再跟第二行的子网掩码做与运算得到192.168.56.0,正是第二行的目的网络地址,因此从eth1接口发送出去;
- 由于192.168.56.0/24正是与eth1接口直接相连的网络,因此可以直接发到目的主机,不需要经路由器转发;
转发过程例2:如果要发送的数据包的目的地址是202.10.1.2
- 依次和路由表前几项进行对比,发现都不匹配;
- 按缺省路由条目,从eth0接口发出去,发往192.168.10.1路由器;
- 由192.168.10.1路由器根据它的路由表决定下一跳地址;
路由表生成算法
路由可分为静态路由和动态路由:
- 静态路由:是指由网络管理员手工配置路由信息。
- 动态路由:是指路由器能够通过算法自动建立自己的路由表,并且能够根据实际情况进行调整。
路由表相关生成算法:距离向量算法、LS算法、Dijkstra算法等。