LINUX网络基础-九-IP协议
LINUX网络基础 [九] - IP协议
一. 关于IP
1.1 什么是IP协议
我数学成绩很好,10次考试6次满分,然后大家都在传,说我有“数学考满分的能力”,那么我一定能做到吗?
不一定,只是有很大的概率考满分
如果我想每次都考满分,该怎么办呢?
我有很大的概率考满分,但是我不想要这个概率。我只想每次都考满分。好在我不光成绩好,我叔、三叔是教导主任。我是个特别执拗的人,考不到满分我就会发脾气,我三叔很宠我。如果本次考试没有考满分,我三叔就会让这次考试无效,重新考。这样就能保证每次都考满分。
其中,三叔是我的上层,而我是真正用来考试执行的人 (如果我每次只能考60多分,那么重复考试就是没有意义的。考100次也不会满分的)
三叔本质是给我 提供策略 ,我是真正“执行考试”的人,没考到满分就重新考,这相当于 超时重传
- 三叔提供策略,就相当于TCP协议,他并没有把数据发到网络里。更多的是在网络协议栈提供可靠性策略,比如说超时重传,快重传,流量控制,拥塞控制,流量窗口
- 真正跑腿办事的是我,我就是IP。
IP协议的本质工作是: 提供一种能力,将数据跨网络从A主机送到B主机
IP地址并不是4字节数据或者点分十进制
用户需要的是:提供一种能力,将数据“ 可靠地 ” 将数据从A主机跨网络送到B主机 ;按照现在的网络,将数据成功送过去的概率很高,但不是100%,所以传输层提供策略,下层提供能力。也就是三叔和我两者结合就能保证“我”每次都能考满分。
1.2 前置认识
数据发送的过程中会经过很多路由器,就好比我们网络基础1的旅游的例子
- 要对所有的主机进行标识,用源ip和目的ip来标识源主机和目的主机; IP分为私有IP和共有IP
- 旅游的例子,我们要先去 故宫 ,得先去 北京 :“去 目标城市 ,去 目标地点 ”;
- 唐僧要去西天的大雷音寺,拜见佛祖求取真经:“ 西天 就是 目标城市 , 大雷音寺 就是 目标地点 ,但是到了目标地点(主机)还不够,还得通过端口找到佛祖这个进程,然后交数据”
所以, IP地址 = 目标网络 + 目标主机
- 任何一个主机都是在某个子网上的,由这个子网的路由器连接,发送数据后要先到达主机B所在的的子网网络(先到达目标网络),然后想办法将报文交给主机B(交给目标主机) –> 依据:路由器的转发机制。(会跨越很多子网)
我们处在一个精心设计的世界中 ,你有身份证号,上学时有学号,上班时有工号,我们有学号但是我们学号,但是不是单纯的数据,是有构成格式的:学号 = 学院编号/专业编号/班级编号/学生编号
你在你们学校捡到了个钱包,你现在想把钱包归还,你最开始是通过一个一个问学生的学号是否匹配上,但是你发现这样效率太低下了。这个归还钱包的过程本质是查找,查找的本质是排除
每个学院都有学生会主席,每个学生会主席都给自家学院建了一个群,然后每个主席又相互建了一个主席群,而且学生会主席肯定知道其它学院的编号,然后我艾特主席,把卡照片发给他,然后主席再把照片发主席群里去
然后主席一看,是电气学院的学号,便艾特了电气学院的主席,然后电气主席说这是我们学院的学号,然后电气主席再把照片发到他的电气学院群里去艾特小美,然后交换联系方式,最后物归原主
上面一顿操作下来 ,让整个校园卡归还过程快速合理,一开始我说不是我学院的,排除了我这个学院的所有人,然后主席找到了电气主席本质是排除了其它学院,就加速了归还过程。
为什么归还的速度变快了?
我把钱包(报文)直接转给计算机学院的学生会主席,本质上是我淘汰了我所在的局域网当中的所有主机,淘汰了一群人。计算机学院的主席此时把数据转发给群里,@了电气学院主席,本质上是淘汰了其他的群。查找的本质是排除,建立群把我们每个人按照学号的方式进行拉群,本质是因为以前一次淘汰一个人,现在一次淘汰一群人。淘汰/排除的效率高了
我们把我 自己的学院编号 叫做 源IP地址 ,把要 归还的校园卡 的学校叫做 目的IP , 各自学院的群 叫做 局域网主机 ,把 主席 叫做 局域网出口路由器 ,把 主席群 叫做 公网。 在这次查找是我们的思路是 ,先找到目标网络,然后再由目标网络找到目标主机
为什么要这样呢,因为在查找的时候效率高,一次可以排除很多东西。唐僧要去西天取经,肯定是排除了路上的其他城市,只选择了到西天的必经城市
二. IP报头字段详解
我们发现,IP报头在宏观上跟TCP报头很相似,所以我们把内核上的协议叫做TCP/IP
两个老问题:
先解决封装和解包的过程 再解决分用的过程
报头和有效载荷如何分离?
有效载荷长度 = 16位总长度 - 固定长度报头, 就能将有效载荷和报头分离
4位首部长度
真实报头长度 = 4位首部长度(假设是x) * 4,范围为[0000, 1111],换成十进制就是[0, 15]
标准报头长度为20字节,那么x就是5,首部长度就是[5, 15],就是[20, 60]字节之间,这和TCP是一模一样的
那我该怎么识别这个IP呢?很简单 我管你多长只需要先读取20个字节,里面的字段都有了
16位总长度
- 代表报文总长度,所以报文长度 = 固定长度报头 + 自描述字段,
- 有效载荷长度 = 总长度 - 固定长度报头, 就能将有效载荷和报头分离
4位版本
这个是固定死的,对于IPv4来说就是4
但是现在有个问题,ip地址是32位,也就是42亿个,现在入网设备太多了,面临着“ IP地址不足 ”的问题
解决方法有很多,NAT,还有IPv6,其中IPv6相当于新的协议了,它用128位来标识,IPv6和IPv4不兼容,IPv6我国最强大,主要用在国内内网,IPv4主要用在公网,这个我们后面讲运营商在讲,现在默认认为是4
8位服务类型
- 丢包问题是无法解决的,这4个选项是为了在进行数据包转发时,给路由器提供转发依据的,提高可靠性,了解一下即可
- 3位优先权字段(已经弃用),4位TOS字段, 和1位保留字段(必须置为0)。4位 TOS分别表示:最小延时,最大吞吐量,最高可靠性,最小成本。这四者相互冲突,只能选择一个。对于 ssh/telnet这样的应用程序,最小延时比较重要;对于ftp这样的程序,最大吞吐量比较重要
比如说你要去云南去玩,可能又非常多的路线和方式供你选择,比如说坐飞机,坐火车,骑自行车。
- 最小延时:从北京到云南路径是最短的
- 最大吞吐量:从北京到云南,单位时间内过去更多的人,哪条路更好
- 最高可靠性:走着走着迷路了,尽量不要走国道,走高速。高速就是最高可靠性
- 最小成本:从北京到云南飞机500 火车100 骑自行车10(水费) 骑自行车就是最小成本
8位生存时间(TTL)
- 数据每经过一个路由器就是一次转发,但是网络太大了可能出bug,而且接收方可能会挂掉无法接收数据,那么IP报文会被无限转发,这种报文称为 流离报文
- 所以我们给每个报文设置一个生存时间,表示该报文在转发的时候能经过的路由器的跳数,每经过一个路由器,生存时间就 -=1,如果为0时,路由器直接丢弃报文
为什么要有8位生存时间
一个报文如果允许能一直转发,可是这种一直转发就会因为目的地址找不到了,时间一久,网络中会出现很多游离报文。他们从A-B B-C C-D D-A… 我们不允许这样的情况存在,所以就有了8位生存时间
8位协议
- 指的就是 我们要把IP的有效载荷交付给上层的哪一个协议
- 下层分离报头和有效载荷后,根据8位协议将有效载荷交付给上层的指定协议
比如填上特定TCP的编号,就可以告诉上方,当前数据包要交给谁了
如何将有效载荷交付给上层?
基于IP协议的传输层协议不止一种,因此当IP从底层获取到一个报文并对其进行解包后,IP需要知道应该将分离后得到的有效载荷交付给上层的哪一个协议。
在IP报头当中有一个字段叫做8位协议,该字段表示的就是上层协议的类型,IP就是根据该字段判定应该将分离出来的有效载荷交付给上层的哪一个协议的。该字段是发送方的IP层从上层传输层获取到数据后填充的,比如是上层TCP交给IP层的数据,那么该数据在封装IP报头时的8位协议填充的就是TCP对应的编号。
32位源IP和32位目的IP
我们以前在进行socket套接字编码的时候,要求填充 ip + port,,端口号将来是给我们的TCP用的不管是源还是目的,ip将来给我们的IP层用的。每发出去个报文,你的源IP地址就是你自己,32位目的IP地址就是对方的IP地址。
现在可以认为:我们 在应用层要把点分十进制的ip字符串转化成4字节的ip是为了填充报头的这两个内容的 ,而32位源IP和32位目的IP是提供给路由器让它进行路径选择的
IP报头当中的32位源IP地址和32位目的IP地址,分别代表的就是该报文的发送端和接收端对应的IP地址。
数据在网络传输过程中会遇到一个个的路由器,这些路由器会帮助网络当中的数据进行路由转发,使得网络中的数据慢慢趋近于目标主机。路由器在帮助数据进行路由转发时,会提取出该数据的IP报头当中的目的IP地址,并以此作为数据路由转发的重要依据。
当接收端收到了发送端发来的数据后,接收端可能也想要给发送端发送数据,因此发送端在发送数据时除了需要指明该数据的目的IP地址,还需要指明该数据的源IP地址,也就是发送端的IP地址。即便接收端收到数据后没有数据想要发送给发送端,但至少接收端需要向发送端发送一个响应报文,表明发送端发送的数据已经被接收端可靠的收到了,因此发送出去的数据除了需要指明该数据的目的IP地址,还需要指明该数据的源IP地址。
理解socket编程:
在进行socket编程的时候,当一端想要发送数据给另一端时,必须要指明对端的IP地址和端口号,也就是发送数据的目的IP地址和目的端口号。
其中这里的IP地址就是给网络层的IP用的,用于数据在网络传输过程中的路由转发,而这里的端口号就是给传输层的TCP或UDP用的,用于指明该数据应该交给上层的哪一个进程。
发送数据时我们不需要指明发送数据的源IP地址和源端口号,因为传输层和网络层都是在操作系统内核当中实现的,数据在进行封装时操作系统会自行填充上对应的源IP地址和源端口号。
唐僧去西天取经的时候,会有人问他,和尚你从哪里来?唐僧会说我从东土大唐而来,我要去西天拜佛求经。这句话说完整就是:我(报文)从东土大唐(源IP)而来,我受唐太宗(源端口号)之命,我要去西天(目标IP),面见如来佛祖(目的端口号)求得真经(数据)
三. 网段划分
3.1 IP地址的构成
IP地址分为两部分:网络号和主机号
- 网络号:保证相互连接的两个网段具有不同的标识
- 主机号:同一段网络内,主机之间具有相同的网络号,但是必须具有不同的主机号
这就好比我们学号的班级加个人编号一样,一个班级内的同学前面的数字是一样的,这叫做同一个网段,后面两个数字或者三个数字不一样,这就是主机号不能相同
- 路由器本质也是一个特定子网的主机,所以路由器它自己也要配置IP地址和主机号
- 路由器实现转发,那么路由器要连接至少两个局域网/子网,所以路由器也一定要配置多个IP地址和主机号 –> 原因:路由器有多张网卡
- 路由器一般是一个子网中的第一台设备,它的IP地址一般都是“网络号.1”
- 路由器的核心功能是IP报文的转发,但是路由器的功能不仅仅如此,比如构建局域网/子网,子网中的主机的IP就是路由器分配的,这个后面公网IP和私有IP再将讲
- 内网IP:如果在子网中新增一台主机, 则这台主机的网络号和这个子网的网络号一致, 但是主机号必须不能和子网中的其他主机重复;并且路由器里面也有操作系统的,所以路由器会对子网IP做管理(DHCP协议)
通过合理设置主机号和网络号, 就可以保证在相互连接的网络中, 每台主机的IP地址都不相同. 那么问题来了, 手动管理子网内的IP, 是一个相当麻烦的事情.
- 有一种技术叫做DHCP, 能够自动的给子网内新增主机节点分配IP地址, 避免了手动管理IP的不便.
- 一般的路由器都带有DHCP功能. 因此路由器也可以看做一个DHCP服务器.
DHCP协议
- DHCP通常用于大型网络环境中,主要工作就是集中地址管理,分配IP地址,使网络中的主机动态获得IP地址,Gateway地址,DNS服务器地址等信息,能够提升地址的使用效率
- DHCP是基于UDP的,一般的路由器都有DHCP,所以路由器也可以看作是DHCP服务器
- 我们连接校园网或者WiFi时,都会要求输入密码,这其实就是路由器在验证你的身份,验证通过后,路由器就会给你动态分配一个IP地址,然后我们就可以进行各种上网动作了
3.2 网段划分
网络开始兴起的时候是32位的IP,可以标识2^32差不多42亿,用完就没了,所以我们可以认为IP地址是一种有限的资源,就意味着各个国家是要竞争IP的
IP分为 网路地址和主机地址 ,曾经提出的划分这两个地址的方式,是 把IP地址分为5类 ,称之为分类划分法:
- 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
但是随着网络发展,这种划分方式问题很快出现:
- 大多数组织都申请的B类网络地址,导致B类网络地址很快就被分完了
- 所以A类浪费了大量的地址,而且每一个子网中的主机号也很难全部用完,例如,申请一个B类地址,理论上一个B类子网能构建6万5千多个主机IP,A类的更多,但是实际上一个子网不会有这么多主机, 因此大量的IP被浪费掉了
- 所以网络的研究员针对性地提出了一种划分方案:CIDR
3.3 子网划分
注意:该方法是针对上面五种IP的类类型提出的,因为可以看到有些IP地主机号太多了,实际情况下不需要这么多主机,所以需要将主机号减少,减少IP的主机数,就能划分出更多子网,减少IP地址浪费
CIDR方案
引入一个额外的子网掩码(subnet mask)来区分网络号和主机号;
子网掩码也是一个32位的正整数. 通常用一串 “0” 来结尾;
将IP地址和子网掩码进行 “按位与” 操作, 得到的结果就是网络号;
网络号和主机号的划分与这个IP地址是A类、B类还是C类无关;
此时一个网络就被更细粒度的划分成了一个个更小的子网,通过不断的子网划分,子网中IP地址对应的主机号就越来越短,因此子网当中可用IP地址的个数也就越来越少,这也就避免了IP地址被大量浪费的情况。
- 比如在某一子网中将IP地址的前24位作为网络号,那么该网络对应的子网掩码的32个比特位中的前24位就为1,剩下的8个比特位为0,将其用点分十机制表示就是255.255.255.0。
- 假设该子网当中有一台主机对应的IP地址是192.168.128.10,那么将这个IP地址与该网络对应的子网掩码进行“按位与”操作后得到的就是192.168.128.0,这就是这个子网对应的网络号。
- 实际在用子网掩码与子网当中主机的IP地址进行“按位与”操作时,本质就是保留了主机IP地址中前24个比特位的原貌,将剩下的8个比特位的值清0了而已,也就是将主机号清0了,所以“按位与”后的结果就是该网络对应的网络号。
特殊的IP地址
并不是所有的IP地址都能够作为主机的IP地址,有些IP地址本身就是具有特殊用途的。
- 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网。
- 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包。
- 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1。
也就是说,IP地址中主机号为全0的代表的是当前局域网的网络号,IP地址中主机号为全1的代表的是广播地址,这两个IP地址都是不能作为主机的IP地址的。
3.4 IP地址不足问题
CIDR虽然一定程度上缓解了IP地址浪费的问题,但是没有增加IP地址的绝对上限,仍然不是很够用,所以有下面三种解决方法:
- 动态地址分配:只给接入网络的设备分配IP地址,因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的,简单来说就是路由器发放和回收IP,在校园网中,我们在宿舍,教室和图书馆接入的校园网,每次的IP都是不相同(共享IP,你要用就给你,不用或用完了还给我)
- NAT技术,能够让不同局域网当中同时存在两个相同的IP地址,NAT技术不仅能解决IP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。
- IPv6:不是IPv4的升级版,是真正变革性的技术,与IPv4毫不相干,是两种不同的协议,用128字节表示一个地址,但是IPv6还没有普及
四. 公网IP和私有IP
私网IP地址的种类
如果一个组织内部组件局域网,在这个局域网内,IP地址只用于局域网内地通信,而不直接连接到公网上,理论上使用任何IP都可以,但是为了规范,RFC 1918 规定了用于组件局域网地私有IP地址:
- 10.* ,前8位是序列号,共16777216个地址
- 172.16.到172.31.,前12位是网络号,共1048576个地址
- 192.168.*,前16位是网络号,共65536个地址
包含在上面三个范围中地,都成为私有IP,其余地都是公网IP,我们连接云服务器时,连接的这个IP就是云服务器地公网IP:
我们连接云服务器时,连接的这个IP地址就是云服务器的公网IP地址。
我们可以通过 ifconfig 命令来查看我们这台机器的私网IP,其中网络接口lo(loop)代表的是本地环回,而eth0代表的就是我这台机器的网络接口,可以看到我的私网IP地址是10.2.20.4
需要注意的是,这里连接云服务器时的IP地址82.157.13.28,是云服务器的公网IP,由于我使用的是腾讯云,因此这里的10.2.20.4是我这个云服务器在腾讯内部的私网IP,可以看到这个IP正好在第一种私网IP范围内
此外,打开Windows当中的cmd窗口,通过
ipconfig
命令可以看到以172.20开头的私网IP
在我们的使用生涯中,我们从一开始使用的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地址替换成路由器的WAN口IP
所以NAT技术主要 用来解决IP不足 的
子网IP可以当作目的IP,但只有一种情况,就是你访问的目标主机就是在你内网当中
路由器是要进行报文转发的,所以必定至少要连接两种网络,一个是内网,一个是运营商内部网络
- 路由器,构建子网
- 路由器都有LAN口IP和WAN口IP
家用路由器理解上和运营商的路由器是性质类似的
其实我们要访问一个公网,本质上报文在我的电脑上要先交到家用路由器,然后再转发给运营商路由器,然后再转发给公网上,然后才能访问。如果你家是电信的,邻居家也是电信的。你俩家里的路由器,在访问的时候会访问同一个运营商路由器
五. 理解运营商和全球网络
我们是怎么上网的?
- 有运营商的工作人员拉网线,然后光纤入户。需要两个设备,一个是调制解调器(猫),路由器,一般是两个盒子。
- 光纤里面有很多玻璃丝,用来传输光信号或者高低电平,然后光纤插到解调器上,解调器的作用是模拟信号转数字,数字信号转模拟,计算机只认识01序列,所以解调器将模拟信号转化成数字信号后转给家用路由器
- 但是光拉网线不行,还得“交钱”,给你个手机号,然后就会给你家路由器一个账号和密码之后,路由器才能上网。
- 同时,路由器还有一个功能就是构建局域网,然后我们的wifi就可以看到了路由器名字了,但是我怕别人来蹭网,于是在除了运营商的账号密码外,还有一个路由器账号和密码,所以路由器里面存在着两套账号密码
关于运营商
- 在上网前有一个步骤非常重要:网络基础设施建设,基础设施建设好了,网民就多了,接着就会孵化出大大小小的互联网公司,然后提供更多工作岗位,推动经济发展
- 但是这个基础建设,是非常耗时耗力的,而且回报周期很长,所以一般的私人企业不愿意做这种活儿,所以咱们国内的那三个公司肯定也不愿意做,但是我们国家“要求”你这么做,同时国家也会大力扶持国企进行基础设施建设,“强迫”运营商去建设
- 在20年前,手机的流量费是非常贵的,下个图片可能5毛钱就没了,所以基础设施搞好,还要降流量费,这样才会有更多人进来
- 而且你不仅要城里的人能上网,还得要村里的人也能上网,所以需要很多基层的工作人员下基层安装维护设备,就是来你家里安装网线的人
- 如果运营商没钱了,国家就来给补给,所以有一个强大的国家,才会有我们国家如此丰富的网络基础设施,让人随时随地都可以上网
关于全球网络
IP地址是一份大的资源, 在分配的时候不是按国家大小来分配的,一般是按照国家组织地区人口综合评估来分发的IP个数的
各个国家是有自己的国际路由器的,这个路由器彼此都是连接的,就类似于我们前面的学生会主席,我们国家的子网掩码是 0000 0010 0000 0000 0000 0000 0000 0000 ,也就是前8位0000 0010
前面8个比特位就不用了,然后每个省也有自己的省路由器,34个省,2^6,然后我们就可以拿着前面的6个比特位来进行编号,然后6+8=14,所以子网掩码就是14位,之后国际路由器也就可以和我们的国内路由器进行通信了
然后每个省有很多市,然后再次分配4个比特位进行编号,到了市路由器之后,子网就变成了14+4=18了。
然后这个地区的ip开头就都是同样的的,假设西安是0000 0010这是国际掩码,然后0000 10这是省路由器掩码,然后00 10这是市编码,后面就是主机号了
一共是 0000 0010 0000 1000 1000 0000 0000 0000 ,换成点分十进制就是 **2 .
8.128.5**
当一个外国人要想访问 2 . 8.128.5 时,先转化为 0000 0010.0000 1000.1000 0000 ,最后一个就是5 –> 0000 0101 ,先发现不是他国内的IP,然后把请求交给美国国际路由器,然后扔到群里面,艾特中国路由器,然后中国路由器再把请求在国内的省路由器群里面艾特了西安,然后到了西安后,西安再问,最后找到2.6.126.5的主机,进行访问
而当请求到了我们国内路由器,之后的所有工作都是由运营商做的
为什么私网IP不能出现在公网当中?
- 不同的局域网中主机的IP地址可能是相同的,所以私网IP无法唯一标识一台主机,因此不能让私网IP出现在公网上,因为IP地址要能唯一标识公网上的一台主机。
- 但由于IP地址不足的原因,我们不能让主机直接使用公网IP而让主机使用私网IP,因为私网IP可以重复也就意味着我们可以在不同的局域网使用相同的IP地址,缓解了IP的不足。
- 此外,我们不能直接使用公网IP还有一个原因就是,因为我们的数据包必须要经过运营商的路由器,如果我们发送的数据直接到了公网,那也就意味着我们再也不用交网费了,这是不现实的。
六. 路由
主机A要把数据发给主机B,是要先根据目标IP,经过路由完成转发,实际是一跳一跳转发的
IP数据包的传输过程中会遇到很多路由器,这些路由器会帮助数据包进行路由转发,每当数据包遇到一个路由器后,对应路由器都会查看该数据的目的IP地址,并告知该数据下一跳应该往哪跳。
我们可以查看当前主机的路由表:
IP数据包的传输过程中会遇到很多路由器,每当数据包到一个路由器后,路由器会查看该数据的目的IP地址,并告知数据下一跳该往哪跳
当IP数据包到达路由器时,路由器就会用该数据的目的IP地址,依次与路由表中的子网掩码 Genmask 进行“按位与”操作,然后将结果与子网掩码对应的目的网络地址 Destination(内网的地址) 进行比对,如果匹配则说明该数据包下一跳就应该跳去这个子网,此时就会将该数据包通过对应的发送接口 Iface 发出。
如果将该数据包的目的IP地址与子网掩码进行“按位与”后,没有找到匹配的目的网络地址,此时路由器就会将这个数据包发送到默认路由,也就是路由表中目标网络地址中的 default 。可以看到默认路由对应的 Flags 是 UG , 实际就是将该数据转给了另一台路由器,让该数据在另一台路由器继续进行路由。
数据包不断经过路由器路由后,最终就能到达目标主机所在的目标网络,此时就不再根据该数据包目的IP地址当中的网络号进行路由了,而是根据目的IP地址当中的主机号进行路由,最终根据该数据包对应的主机号就能将数据发送给目标主机了。
查路由表是怎么查的呢?
拿着目标主机的IP地址,按位与&上路由表中的子网掩码,然后和Destination做对比,如果比对不成功,如果不是就直接对比下一个掩码和Destination,如果对比成功,那么表示目标网络正确,就通过eth0把数据发送出去
路由器的查找结果可能有以下三种:
- 路由器经过路由表查询后,得知该数据下一跳应该跳到哪一个子网。
- 路由器经过路由表查询后,没有发现匹配的子网,此时路由器会将该数据转发给默认路由(一般指的是同网段的另一台路由器)。
- 路由器经过路由表查询后,得知该数据的目标网络就是当前所在的网络,此时路由器就会将该数据转给当前网络中对应的主机。
假设某主机上的网络接口配置和路由表如下:
- 这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到 192.168.56.0/24网络;
- 路由表的Destination是目的网络地址,Genmask是子网掩码,Gateway是下一跳地址,Iface是发送接 口,Flags中的U标志表示此条目有效(可以禁用某些 条目),G标志表示此条目的下一跳地址是某个路由器的 地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发;
转发过程例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路由器根据它的路由表决定下一跳地址;
七. IP报文的分片与组装
实际上,在一台主机中,报文并没有通过网络层直接发出去,而是继续交给了自己的下一次协议(数据链路层,属于网卡的驱动层,还有物理层)数据链路再去转发给路由器或者同一个网段的主机。
但是数据链路层,无法一次发送过大的报文,所以就要求上层不能给我交付过大的报文 。(这就是为什么你可以直接发送的数据是64KB,但是你还要用滑动窗口把一段很长的数据,分成一个个的数据段)
ifconfig命令可以查看当前协议栈的一些信息,其中下面红框框的 mtu 表示当前的数据链路层的MAC帧一次最多发送1500字节的数据,这个数据包括IP的报头和IP的有效载荷
但是,如果一个报文超过1500字节,但是数据链路层又不得不发,这时候就会对报文进行分片, 而且既然有分片,那么必定有组装,所以就要求IP报头里包含分片组装的相关信息:
- 其中16位标识就是IP报文的编号,分片之后的IP报文编号是相同的
- 对于3位标志位字段,第二位为0,标识允许切片,第三位用来结束标记,表示当前是否是最后一个小片,是的话为0,不是为1
- 对于13位偏移,假设一个报文都分成了很多片,这个偏移量表示这个小片在原来的大报文里的偏移量,用于组装报文
- 对于分片后的每个IP报文,都会重新添加IP报头的
你怎么知道报文分片了呢?
只要我收到了后面的切片部分,那么片偏移一定不为0 。如果片偏移为0,我们还有个三位标识符的结束标识。
简单来说,
- 如果一个IP报文不是分片的,那么片偏移=0,3位标志位里的更多分片=0。
- 如果一个不为0那么就是分片的
总结:片偏移 != 0 || 更多分片 == 1,只要符合任意一个条件,就说明这个IP是被分片
如何组装的?
- 先确保将所有的分片全都聚在一起(相通的标识)
- 然后通过片偏移排序(完成组装)
- 去掉报头然后拼接
如何知道切片报文是否丢失?
丢失报文有丢失,那么一般是三种情况:1,丢第一个 2,丢中间的 3,丢最后一个
- 如果丢了第一个,如果根据3位标志里的片偏移排序时没有一个报文的片偏移是0的,就能甄别出来
- 如果丢最后一个,收到的报文没有任何一个3位标志里的更多分片结束标记为0,那么就认为丢最后一个
- 对于丢中间,在进行排序时,第一个报文长度就是下一个报文的片偏移,假设三个1500长度的报文,第一个片偏移是0,排完序后第二个直接就是3000了,但是我们两个报文片偏移加起来才1500,那么我可以认为第二个报文丢了,识别出丢中间
建不建议分片呢?
不建议 。因为在IP当中,如果有任意一个分片丢失导致组装失败,那么在TCP看来就相当于整个报文丢失了,会进行全部重发,所以 分片可能会增加丢包概率,降低传输效率
但是具体是UDP,TCP说了算,IP是个跑腿的。就要求TCP发送报文不要发送过大的报文了,也就想到了TCP滑动窗口一大块数据为什么分多次发了,那TCP也不知道这个发的报文最大是多少呢?那就和TCP的三次握手又有关系了,握手双方是会交换自己单个发送报文的数据量的大小的…
为什么分片之后每一个都要带上报头?
因为如果不带报头的话,就没有16位标识,3位标志,13位片偏移了,就没办法组装了
例子
假设有一个IP数据包,总长度为 4000字节 ,其中 IP报头为20字节 , 数据部分为3980字节 。现在,网络的MTU为1500字节,也就是说,每个传输的分片的总长度不能超过1500字节。那么,每个分片能携带的数据部分最大为:
- 最大数据部分 = 1500 - 20 = 1480字节
但是, 由于IP分片要求数据部分长度必须是8字节的整数倍 (除了最后一个分片),所以实际每个分片中能携带的数据部分应取小于等于1480且是8的倍数的最大值,即1472字节。
因此,原数据3980字节会分成如下3个分片:
分片1
- IP报头 :20字节
- 数据部分 :1472字节(原数据的字节0到1471)
- 总长度 :20 + 1472 = 1492字节
- 分片偏移 :0(单位为8字节,即起始位置为0)
- 标识字段 :假设为12345(所有分片该字段相同,用于重新组装时识别同一数据包)
- 标志字段 :MF(More Fragments)位置1,表示后面还有更多分片
分片2
- IP报头 :20字节
- 数据部分 :1472字节(原数据的字节1472到2943)
- 总长度 :1492字节
- 分片偏移 :1472/8 = 184(表示数据从原数据的第184×8 = 1472个字节处开始)
- 标识字段 :12345
- 标志字段 :MF位置1,表示后面还有更多分片
分片3
- IP报头 :20字节
- 数据部分 :剩余数据3980 - 1472 - 1472 = 1036字节(原数据的字节2944到3979)
- 总长度 :20 + 1036 = 1056字节
- 分片偏移 : (1472 + 1472) / 8 = 368
- 标识字段 :12345
- 标志字段 :MF位置0,表示这是最后一个分片
这样,在目的地,接收方会根据相同的标识字段(12345)、分片偏移以及MF标志将这些分片重新组装回原来的4000字节的数据包。
我们在面试的时候可能会遇到这样的问题
一般面试官问到网络,几乎都会问:请你帮我解释下,一个HTTP请求从发到服务器,到你最终拿到响应的整个过程
你要谈的话,是不是要从应用层HTTP的request respond,可是这俩都是数据,要交给TCP,交给TCP就会面临可靠性问题,拥塞控制,流量控制等问题,就会面临面向连接的丢包重传的问题,你再想谈,TCP报文再向下就是IP问题,IP问题你可能又涉及到路由问题和分片问题。朋友们,细节你聊的越多,人家面试官才能认识到你是真的听懂了