目录
- 基本概念
- IP协议格式
- 分片与组装
- 分片
- 组装
- 网段划分
- 特殊的IP地址
- IP地址的数量限制
- 私有IP地址和公网IP地址
- 路由
基本概念
TCP作为传输层控制协议,其保证的是数据传输的可靠性和传输效率,但TCP提供的仅仅是数据传输的策略,而真正负责数据在网络中传输的则传输层之下的网络层和数据链路层。
双方在进行网络通信的过程中,并不是直接在双方传输层之间进行数据传输的,而是发送方通过传输层向下进行交付,在网络层和数据链路层进行封装以后发送给对端主机,而对端主机收到数据后同样也在网络层和数据链路层进行解包,传输层才能拿到数据,最后在向上交付。
我们是IP协议作为网络层协议,解决的就是提供一种能力,将数据可靠的从主机A发送到主机B的能力。
注意:
- 双方进行TCP网络通信时,首先我们的发送方需要拥有给对方主机发送数据的能力,没有给对方主机发送数据的能力也就意味着数据在可靠他也发不出去;
- 发送方也并不是每次发送数据都可以成功的,但如果发送方连将数据发送给对方的能力都没有,那发送方基本就不可能将数据发送给对方。
- 一旦发送方有了将数据发送给对方的能力,就算发送方某次发送的数据没有成功到达对方,此时上层TCP由于没有收到对应数据的应答,此时上层TCP会要求进行数据重发,直到数据成功发送到对方主机为止。
也就是说,在网络层有能力将数据送到对方主机的情况下,虽然网络层不能保证每次都能将数据成功送到对方主机,但在TCP提供的可靠性策略的保证下,最终网络层就一定能够将数据可靠的发送到对方主机。
路径选择
数据进行的网络传输一般都是跨网络的,而路由器就是连接多个网络的硬件设备,因此数据在进行跨网络传输时一定需要经过多个路由器。
数据在知道自己的目的主机以后,就会寻找最短路径到达该目的地。
- 目的地的确定是非常重要的,因为目的地直接决定了数据路由时的路径选择,这也是跨网络找到目标主机的根本。
- 只有数据经过了较为正确的路径选择,最终才可能慢慢趋近于目标网络或目标主机。
确定数据路由的目的地后,数据就可以在网络中进行路由了,但数据在路由时无法自行进行路径选择,因为这个数据本身是“不认识路”的,因此数据在路由的过程中需要不断“找路人问路”,而这里所谓的“路人”就是网络当中的一台台路由器。
网络当中的路由器是“认识路的”,它们将自己的“认路经验”都记录到路由表当中,因此路由器可以通过查路由表找到去特定点的最短路径。因此数据在路由时,会不断通过路由器来进行路径选择,以此来一步步靠近目标网络或目标主机。
- 主机:配有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报文(IP报头+有效载荷)的总长度,用于将各个IP报文进行分离。
- 16位标识(id):唯一的标识主机发送的报文,如果数据在IP层进行了分片,那么每一个分片对应的id都是相同的。
- 3位标志字段:第一位保留,表示暂时没有规定该字段的意义。第二位表示禁止分片,表示如果报文长度超过MTU,IP模块就会丢弃该报文。第三位表示“更多分片”,如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。
- 13位片偏移(framegament offset):分片相对于原始数据开始处的偏移,表示当前分片在原数据中的偏移位置,实际偏移的字节数是这个值× 8 \times 8×8得到的。因此除了最后一个报文之外,其他报文的长度必须是8的整数倍,否则报文就不连续了。
- 8位生存时间(Time To Live,TTL):数据报到达目的地的最大报文跳数,一般是64,每经过一个路由,TTL -= 1,一直减到0还没到达,那么就丢弃了,这个字段主要是用来防止出现路由循环。
- 8位协议:表示上层协议的类型。
- 16位首部检验和:使用CRC进行校验,来鉴别数据报的首部是否损坏,但不检验数据部分。
- 32位源IP地址和32位目的IP地址:表示发送端和接收端所对应的IP地址。
- 选项字段:不定长,最多40字节
如何分离?
IP分离报头与有效载荷的方法与TCP是一模一样的,当IP从底层获取到一个报文后,虽然IP不知道报头的具体长度,但IP报文的前20个字节是IP的基本报头,并且这20字节当中涵盖4位首部长度。
-当IP从底层获取到一个报文以后,首先读取报文的前20个字节,并且提取4位首部长度,此时就获取了IP报头大小size;
- 如果size值大于20字节,则需要继续从报文当中读取size−20字节的数据,这部分数据就是IP报头当中的选项字段;
- 读取完IP的基本报头和选项字段后,剩下的就是有效载荷了。
需要注意的是这里的4位首部长度跟TCP的4位首部长度没什么区别:
4位二进制的取值范围是0000 ~ 1111,因此IP报头的最大长度为15×4=60字节,因为基本报头的长度是20字节,所以IP报头中选项字段的长度最多是40字节。如果IP报头当中不携带选项字段,那么IP报头的长度就是20字节,此时报头当中的4位首部长度字段所填的值就是20÷4=5,即0101。
如何交付?
基于IP协议的上层传输层协议不止一种,因此当IP从底层获取到一个报文并对其进行解包后,IP需要知道应该将分离后得到的有效载荷交付给上层的哪一个协议。
在IP报头当中有一个字段叫做8位协议,该字段表示的就是上层协议的类型,IP就是根据该字段判定应该将分离出来的有效载荷交付给上层的哪一个协议的。该字段是发送方的IP层从上层传输层获取到数据后填充的,比如是上层TCP交给IP层的数据,那么该数据在封装IP报头时的8位协议填充的就是TCP对应的编号。
32为源IP地址与目的IP地址
在IP协议中,源IP地址代表发送端IP地址,目的IP地址地址代表接收方IP地址。
数据在网络中尽显传输时,并不是一步到位的,而是通过一个个路由器进行转发,最终数据慢慢趋近于目标主机,路由器在进行路由转发的过程中,就会提取出该IP报文中的目的IP地址,以此为进行下一步操作;
对于发送方来说,我们需要将数据发送到对端主机,就需要知道目的IP地址,只有知道了目的IP地址以后,我们才能将数据顺利的发送到目的地。对于接收端来说,我们可能会接收到数据以后再向发送端发送数据,即使不发送数据,我们也要给发送方形成一个响应报文才可以,所以既需要源IP地址也需要目的IP地址。
理解socket编程
- 进行socket编程的时候,我们需要知道接收方的目的IP地址和目的端口号,这样才能成功的将数据发送到对端主机;
- 目的IP地址其实是给网络层IP用的,而目的端口号其实TCP/UDP协议中用于指明该数据应该交于上层的哪一个进程;
- 而我们发送数据过程中并不需要指明发送数据的源端口号和源IP地址,因为传输层和网络层都是在操作系统内核当中实现的,数据在进行封装时操作系统会自行填充上对应的源IP地址和源端口号。
8位生存时间
报文在网络传输过程中,可能因为某些原因导致报文无法到达目标主机,比如报文在路由时出现了环路路由的情况,或者目标主机已经异常离线了,此时这个报文就成了一个废弃的游离报文。
为了避免网络当中出现大量的游离报文,于是在IP的报头当中就出现了一个字段,叫做8位生存时间(Time To Live,TTL)。8位生存时间代表的是报文到达目的地的最大报文跳数,每当报文经过一次路由,这里的生存时间就会减一,当生存时间减为0时该报文就会被自动丢弃,此时这个报文就会在网络中消散。
分片与组装
分片
数据链路层
数据在网络中进行传输,是通过一个个的路由器进行路由转发,比如我们的数据需要从主机A发送到主机C,可能就需要从路由器A转发到路由器B,在转发到路由器C… …经过一系列转发操作以后到达主机B,而在数据从一个结点转发到下一个节点的就是通过数据链路层来实现的。
为什么要进行分片?
每一种物理网络都会规定链路层数据帧的最大长度,称为链路层MTU(Maximum Transmission Unit).IP协议在传输数据包时,若IP数据报加上数据帧头部后长度大于MTU,则将数据报文分为若干分片进行传输,并在目标系统中进行重组。比如说,在以太网环境中可传输最大IP报文大小(MTU)为1500字节。如果要传输的数据帧大小超过1500字节,即IP数据报长度大于1472(1500-20-8=1472,普通数据报)字节,则需要分片之后进行传输。
什么是分片?
分片就是将一个比较大的报文,拆成多个小的,满足条件的报文,分片的行为是网络层做的,同样,组装的行为也是对端网络层做的,对于TCP/UDP,将数据传输给下层以后,他其实并不关心下层是怎么将数据发送的(我将一个完整的数据发送给你,就必须传输回来的数据也是完整的,至于怎么实现,就是网络层的事情)。
如何实现分片?
分片的实现是由我们IP报头中的16位标识,3位标志,13位片偏移来决定的:
- 16位标识
是唯一标识主机发送的报文,如果数据在IP层进行了分片,那么每一个分片报文的16位标识是相同的,也就是说,相同报文的分片,标识是相同的,不同报文,标识是不同的。
- 3位标志
第一位保留,表示暂时没有规定该字段的意义。第二位表示禁止分片,表示如果报文长度超过MTU,IP模块就会丢弃该报文。第三位表示“更多分片”,如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。
- 13位片偏移
分片相对于原始数据开始处的偏移,表示当前分片在原数据中的偏移位置,实际偏移的字节数是这个值×8得到的。因此除了最后一个报文之外,其他报文的长度必须是8的整数倍,否则报文就不连续了。
我们假设IP层需要发送3000个字节的数据,此时就需要我们进行分片,假设IP报头的长度就为20个字节,需要注意的是,对于每一个分片我们都需要封装一个20字节的报头,所以3000个字节数据来说我们就需要进行3次分片。
对于这三个分片来说,他们的16位标识是一样的,假设16位标识位1234,则这3个分片报文对应的16位标识,3位标志中的“更多分片”和13位片偏移分别如下:
我们会发现,偏移量+自身大小 = 下一个报文的偏移量。
如何识别分片还是未分片?
我们可以根据3位标志中的更多分片来识别,如果更多分片标志位为1,我们就可以确定他被分片了,如果更多标志位为0并且13位偏移量也为0,就证明没有被分片。
组装
双方进行网络间通信,不仅仅是需要将数据发送出去的,还需要将数据向上交付,我们知道TCP/UDP发送给网络层是一个完整的数据,那么我们在进行数据向上交付的时候,也需要一个完整的数据,这就需要我们对分片的报文进行组装了。
如何识别分片的开始,中间,结尾?
我们想要组装一个完整的报文,就必须识别出分片报文的开始,中间和结尾,通过三位标志中的更多分片和13位偏移我们就能识别出来:
- 开始:更多分片为1,片偏移为0;
- 中间:更多分片为1,片偏移不是0;
- 结尾:更多分片为0,片偏移不是0。
虽然中间报文存在多个,但是我们依然可以根据偏移量最终将一个完整的报文组装起来,结合(偏移量 + 自身大小 = 下一个偏移量),我们就可以进行升序排序,一旦我们扫描结果不匹配,必定是中间报文出现丢失了,如果成功计算到结尾,就一定是收取完整了。
在我们的网络层中可能存在大量分片以后的报文,我们在进行组装的过程中需要在大量分片报文中识别出一个完整报文的开头,中间和结尾,又是如何做到的呢?
这也就是我们在进行分片过程中为什么每一个分片报文必须有一个IP报头的原因,IP报头中保存了16为标识和32位源IP地址,一个完整报文分片以后他的每一份分片报文的16位标识是一样的,因此IP可以通过IP报头当中的32位源IP地址和16位标识,将经过分片的数据各自聚合在一起,聚合在一起后就可以开始进行组装了。
为什么不建议进行分片?
虽然我们的传输层并不关心网络层分片的问题,但是分片确是会对传输层产生影响的:
- 如果一个报文没有被分片,那么只要接收端收到了这一个报文,我们就可以认为该数据被对方可靠的收到了。
- 如果一个报文被分片了,只有接收端收到了所有分片组成的一个完整报文,我们才可以认为该数据被对方可靠的收到了,接收端收到一个完整报文的前提是这些分片报文并不能出丢包问题,一旦其中有一个报文出现了丢包问题,接收端就不可能组装一个完整报文,这时接收端会将收到的分片报文全部丢弃,此时传输层TCP会因为收不到对方应答而进行超时重传。
- 假设在网络传输时丢包的概率是万分之一,如果将数据拆分为一百份进行发送,那么此时丢包的概率就上升到了百分之一。因为只要有一个分片报文丢包了也就等同于这个报文整体丢失了,因此分片会增加传输层重传数据的概率。
只要分片报文当中的某一个出现了丢包,此时传输层都需要将数据整体进行重传,因为传输层并不知道底层IP对数据进行了分片,当传输层发送出去的数据得不到应答时传输层就只能将数据整体进行重传,因此数据在发送时不建议进行分片。
如何尽可能避免分片?
实际数据分片的根本原因在于传输层一次向下交付的数据太多了,导致IP无法直接将数据向下交给MAC帧,如果传输层控制好一次交给IP的数据量不要太大,那么数据在IP层自然也就不需要进行分片。
- 因此TCP作为传输控制协议,它需要控制一次向下交付数据不能超过某一阈值,这个阈值就叫做MSS(Maximum Segment Size,最大报文段长度)。
- 通信双方在建立TCP连接时,除了需要协商自身窗口大小等概念之外,还会协商后续通信时每一个报文段所能承载的最大报文段长度MSS。
MAC帧的有效载荷最大为MTU,TCP的有效载荷最大为MSS,由于TCP和IP常规情况下报头的长度都是20字节,因此一般情况下 MSS = MTU - 20 - 20,而MTU的值一般是1500字节,因此MSS的值一般就是1460字节。
所以一般建议TCP将发送的数据控制在1460字节以内,此时就能够降低数据分片的可能性。之所以说是降低数据分片的可能性,是因为每个网络的链路层对应的MTU可能是不同的,如果数据在传输过程中进入到了一个MTU较小的网络,那么该数据仍然可能需要在路由器中进行分片。
网段划分
IP地址分为两个部分,网络号和主机号:
- 网络号:保证相互连接的两个网段具有不同的标识;
- 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号。
下图中路由器连接了两个网段。对于网络标识来讲,同一网段内主机的网络标识是相同的,不同网段内主机的网络标识是不同的。而对于主机标识来讲,同一网段内主机的主机标识是不同的,不同网段内主机的主机标识是可以相同的。
- 不同的子网其实就是把网络号相同的主机放到一起。
- 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。
DHCP协议
通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同。但是手动管理P地址是一个非常麻烦的事情,当子网中新增主机时需要给其分配一个IP地址,当子网当中有主机断开网络时又需要将其IP地址进行回收,便于分配给后续新增的主机使用。
因此对于IP地址的分配和回收一般不会手动进行,而是采用DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)技术。
- DHCP通常被应用在大型的局域网环境中,其主要作用就是集中地址管理、分配IP地址,使网络环境中的主机动态获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。
- DHCP是一个基于UDP的应用层协议,一般的路由器都带有DHCP功能,因此路由器也可以看作一个DHCP服务器。
当我们连接WiFi时需要输入密码,本质就是因为路由器需要验证你的账号和密码,如果验证通过,那么路由器就会给你动态分配了一个IP地址,然后你就可以基于这个IP地址进行各种上网动作了。
数据在网络中如何传输?
当IP要将数据通过网络从一台主机发送到另一台主机时,并不是直接进行发送的,而是先将数据发送到目标主机所在的网络,然后再将数据发送到目标主机。
发送数据之所以不是直接发送到目标主机是因为效率太低了:
- 我们在网络中进行数据发送的过程本质上是排除的过程,而如果直接排查主机的话一次就只能排查一个主机,效率就极低了;
- 如果我们一开始以网络为目标,就可以排除大量的主机,因为同一网段内肯定是存在大量主机的,我们以以网络为目标,在查找过程中就能一次排除大量和目标主机不在同一网段的主机,这样就可以大大提高检索的效率。
因此,为了提高数据路由的效率,我们对网络进行了网段划分。
网段划分
过去曾经提出一种划分网络号和主机号的方案,把所有IP 地址分为五类,如下图所示:
各类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地址的前五个比特位,第几个比特位最先出现0值,那么这个IP地址对应就属于A、B、C、D、E类地址。
子网划分
随着Internet的飞速发展,这种划分方案的局限性很快显现出来:
- 大多数组织都申请B类网络地址, 导致B类地址很快就分配完了,而A类却浪费了大量地址;
- 由于B类地址的主机号占16个比特位,因此理论上一个B类网络当中允许有65536台主机;
- 但实际网络架设中,一般不会存在一个局域网当中有这么多主机的情况,也就意味着大量的IP地址实际都被浪费掉了。
针对这种情况提出了新的划分方案,称为CIDR(Classless Interdomain Routing):
- 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号,本质是借用主机号当中的若干位来充当网络号;
- 子网掩码也是一个32位的正整数,通常用一串 “0” 来结尾;
- 将IP地址和子网掩码进行 “按位与” 操作,得到的结果就是网络号;
- 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关。
此时一个网络就被更细粒度的划分成了一个个更小的子网,通过不断的子网划分,子网中IP地址对应的主机号就越来越短,因此子网当中可用IP地址的个数也就越来越少,这也就避免了IP地址被大量浪费的情况。
可见,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地址本身就是具有特殊用途的。
- 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网。
- 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包。
- 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1。
也就是说,IP地址中主机号为全0的代表的是当前局域网的网络号,IP地址中主机号为全1的代表的是广播地址,这两个IP地址都是不能作为主机的IP地址的。因此在某个局域网中最多能存在的主机个数是 2^主机号位数 - 2。
IP地址的数量限制
我们知道,IP地址(IPv4)是一个4字节32位的正整数。那么一共只有2的32次方个IP地址,大概是43亿左右。而TCP/IP协议规定,每个主机都需要有一个IP地址。
这意味着,一共只有43亿台主机能接入网络么?
实际上,由于一些特殊的IP地址的存在,数量远不足43亿;另外IP地址并非是按照主机台数来配置的,而是每一个网卡都需要配置一个或多个IP地址。
-CIDR虽然在一定程度上缓解了IP地址不够用的问题,因为CIDR提高了IP地址的利用率,减少了浪费,但IP地址的绝对上限并没有增加。仍然不是很够用,这时候有三种方式来解决:
- 动态分配IP地址:只给接入网络的设备分配IP地址,因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的,避免了IP地址强绑定于某一台设备。
- NAT技术:能够让不同局域网当中同时存在两个相同的IP地址,NAT技术不仅能解决IP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。
- IPv6:IPv6用16字节128位来表示一个IP地址,能够大大缓解IP地址不足的问题。但IPv6并不是IPv4的简单升级版,它们是互不相干的两个协议,彼此并不兼容,因此目前IPv6还没有普及。
私有IP地址和公网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)。
我们可以通过ifconfig命令来查看我们这台机器的私网IP,其中网络接口lo(loop)代表的是本地环回,而eth0代表的就是我这台机器的网络接口,可以看到我的私网IP地址是10.0.28.16。
打开Windows当中的cmd窗口,通过ipconfig命令可以看到大量以192.168开头的私网IP。
数据在服务器之间的传输过程
我们的路由器对内面对的是自己构建的子网,对外自己本身也是别人构建的子网的一个主机,路由器是连接两个或多个网络的硬件设备,在路由器上有两种网络接口,分别是LAN口和WAN口:
- LAN口:表示连接本地网络的端口,主要与家庭网络中的交换机、集线器或PC相连;
- WAN口:表示连接广域网的端口,一般指互联网。
大致关系就如下:
- 我们会发现不同的路由器,子网IP都是一样的,这也就说明了子网内的主机IP地址不能重复,但是子网之间的IP地址就可以重复了,这也就大大缓解了IP不足的问题;
- 由于LAN口IP和 WAN口IP的存在,才能使得我们的数据在服务器之间才能够传输,我们发送一个报文,路由器会将源IP替换成路由器的WAN口IP,除开公网路由器,每经过一个运营商的路由器就都会完成这个工作;
- 这种源IP在不同内网,不同层级之间网络节点进行转发,然后被替换,最终数据包中的IP地址成为一个公网IP,这种技术叫做NAT;
所以数据要从一个局域网发送到另一个局域网,如果不经过公网是基本上不可能的。我们在和别人聊天的时候,也不是直接将数据从一个局域网直接发送到了另一个局域网,而是先将数据经过公网发送到了服务器,然后再由服务器将数据经过公网转发到了另一个局域网。
为什么私网IP不能出现在公网当中?
- 不同的局域网中主机的IP地址可能是相同的,所以私网IP无法唯一标识一台主机,因此不能让私网IP出现在公网上,因为IP地址要能唯一标识公网上的一台主机。
- 但由于IP地址不足的原因,我们不能让主机直接使用公网IP而让主机使用私网IP,因为私网IP可以重复也就意味着我们可以在不同的局域网使用相同的IP地址,缓解了IP的不足。
- 此外,我们不能直接使用公网IP还有一个原因就是,因为我们的数据包必须要经过运营商的路由器,如果我们发送的数据直接到了公网,那也就意味着我们再也不用交网费了,这是不现实的。
路由
数据在路由的过程中,实际就是一跳一跳(Hop by Hop)“问路”的过程。所谓“一跳”就是数据链路层中的一个区间,具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间。
IP数据包的传输过程中会遇到很多路由器,这些路由器会帮助数据包进行路由转发,每当数据包遇到一个路由器后,对应路由器都会查看该数据的目的IP地址,并告知该数据下一跳应该往哪跳。
- 路由器经过路由表查询后,得知该数据下一跳应该跳到哪一个子网。
- 路由器经过路由表查询后,没有发现匹配的子网,此时路由器会将该数据转发给默认路由。
- 路由器经过路由表查询后,得知该数据的目标网络就是当前所在的网络,此时路由器就会将该数据转给当前网络中对应的主机。
路由表可以通过route
命令进行查看:
- Destination代表的是目的网络地址。
- Gateway代表的是下一跳地址。
- Genmask代表的是子网掩码。
- Flags中,U标志表示此条目有效(可以禁用某些条目)G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发。
- Iface代表的是发送接口。
当IP数据包到达路由器时,路由器就会用该数据的目的IP地址,依次与路由表中的子网掩码 Genmask
进行“按位与”操作,然后将结果与子网掩码对应的目的网络地址Destination
进行比对,如果匹配则说明该数据包下一跳就应该跳去这个子网,此时就会将该数据包通过对应的发送接口Iface
发出。
如果将该数据包的目的IP地址与子网掩码进行“按位与”后,没有找到匹配的目的网络地址,此时路由器就会将这个数据包发送到默认路由,也就是路由表中目标网络地址中的default
。可以看到默认路由对应的Flags
是UG,实际就是将该数据转给了另一台路由器,让该数据在另一台路由器继续进行路由。
数据包不断经过路由器路由后,最终就能到达目标主机所在的目标网络,此时就不再根据该数据包目的IP地址当中的网络号进行路由了,而是根据目的IP地址当中的主机号进行路由,最终根据该数据包对应的主机号就能将数据发送给目标主机了。