- 应用层(http、https): 数据的使用。
- 传输层(UDP、TCP):网络通讯的细节,将数据可靠的从A主机跨网络送到B主机。
- 网络层(IP):提供一种能力,将数据从A主机送到B主机的能力。
- ……
IP协议是一种能力(非100%),所以就必须得有上层给提供的一些策略,来保证诸如丢包了怎么办、发送过去的报文对方不要怎么办、IP出现一些不可靠现象有谁来保证IP报文的可靠现象?
其中就由TCP来保证,所以TCP提供可靠性 / 效率,而IP为我们提供能力,所以TCP与IP就能够做到将数据从A主机,可靠的跨网络经过路径转发,将数据从A主机送至B主机。这就是传说中的TCP/IP协议,这就是网路通讯时所需要解决的首要问题。
当学习完IP后可以发现,TCP与IP之间,是以层状形式体现出来的两层不同协议,但是二者也是必须协同起来,然后才能将数据从A主机可靠的送到B主机。
可以将TCP想象为老板,IP想象为员工。发起与接收都是发起者的接收方TCP层,接收者的接收方的TCP层,正真的执行者是IP层。
目录
IP协议
基本概念
协议头格式
4位首部长度
8位协议
4位版本
8位的服务类型
16位总长度(字节数)
8位生存时间
16为首部校验和
IP地址
小结
报头的第二行
知识铺垫
概念
原理 - 概述
原理 - 具体
网段划分
知识铺垫
子网
概念
特殊的IP地址
IP地址的数量限制
私有IP地址和公网IP地址
报文推送(NAT技术)
路由
总结
IP协议
数据并不是从一个机器直接飞到对应的对方主机的,而是数据必须经过跳转路由器,然后再由路由器的转发送到下一个路由器,依次这样一跳一跳的到达目标主机 —— 数据转发的过程。一跳一跳的原则就是根据IP地址,来进行路径选择的。所以目的IP为我们提供了目标来让我们可以将数据从主机B到主机C的过程。
基本概念
- 主机:配有IP地址,狭义上:A、B、C、D;广义上:图中都是。
- 路由器:即配有IP地址,又能进行路由控制。
- 节点:主机和路由器的统称。
协议头格式
- IP协议也就是一个报文结构,这个报文结构在Linux内核当中也就是一个位段。
- IP协议所对应的报头和有效载荷数据,最后一定需要做到可以被分离。
- 数据:
#问:几乎任何协议都要首先解决的两个问题:a、如何分离(封装)? b、如何交付(分用)?
- 如何分离(封装)?
IP协议是属于固定长度的报文:前20字节。
我们就可以通过先读取前20个字节,就能够读取到IP协议报文的报头中的相关属性了。
4位首部长度
IP也是有选项的,所以其时先读取前20字节,然后再读取4位首部长度,再拿着其减去20字节就是选项的长度。
所以:对于如何分离(封装)?其是采用定长报头 + 自描述字段(4位首部长度),以此将报头和有效载荷进行分离。
4位首部长度,其是在标准长度20字节的长度里的,其包括20字节和选项长度。取值范围:0000 ~ 1111 = 0 ~ 15,但是标准长度报头就是20字节了啊,更何况还会有选项的边长。其实它的单位不是字节,而是4字节 -> 0*4 ~ 15*4,所以一个真实的IP报头长度是:[20,60]。
- 如何交付(分用)?
8位协议
8位协议里面用于表明了,有效载荷部分是UDP还是TCP,表明须交付给哪一个协议。
4位版本
4位版本号(version):指定IP协议的版本,对于IPv4来说,就是4。
#:IPv4与IPv6
- IPv4
4字节、32bit位来表示IP地址。
- IPv6
主要原因是IPv4是由23位表示,所以数量上全球只能有 2^23 个IP地址,只有42亿多,现在远远不够了,但是现在网络没有崩是因为使用到了一些技术,而彻底的解决的方案就是IPv6。IPv6选择的是使用128位的bit位来表示IP地址,数量上全球能有 2^128 个IP地址使用,所以量是极其大的。
但是有一个遗憾,就是IPv4和IPv6是不兼容的,想要切换就相当于将量极其庞大的安卓手机全部切换为IOS系统。
8位的服务类型
8位服务类型(Type Of Service): 3位优先权字段(已经弃用),4位TOS字段,和1位保留字段(必须置为0)。4位TOS分别表示(IP报文转发的时候设置转发属性):最小延时(不要在路由器里排太长的时间),最大吞吐量(转发时可以对IP报文进行一定的累积),最高可靠性(尽量选择可靠的路径来进行转发),最小成本。这四者相互冲突,只能选择一个。对于 ssh / telnet 这样的应用程序,最小延时比较重要,对于 ftp 这样的程序,最大吞吐量比较重要。
16位总长度(字节数)
IP报文由4位首部长度去掉报头,16位总长度减去4位首部长度得到有效载荷数据的长度。有效载荷 = 16位总长度 - 4位首部长度*4。
8位生存时间
每一个IP协议报文在进行转发的时候,有一个概念 —— 生存时间。
当一个IP报文在路上转发的时候,有可能会因为路由器本身的BUG问题,而导致其在某一个局部网络当中进行来回的互相转发。为了避免此类在网路中转发过于长的时间,所以设置了一个8位生存时间。
#问:网络里面怎么会出现这种情况?
首先,现在的网络已经特别特别的大了,而且大家的技术标准虽然都是采用统一的TCP、IP这些协议,但是底层可能还是会有差异。包括,不同厂商生产出来的设备也有差异,包括转发所匹配的算法也有差异。太庞大、太复杂了。所以并不能排除在网络中存在的一些潜在的数据黑洞(数据进去就出不来了)。
如果没有8位生存时间,结果就可能会导致一些IP报文数据一直在网络中存在,而长时间的转发中已经丧失了其本身的意义,于是这样长此以往的转发中,每一次转发都是在浪费资源。
8位生存时间本质上就是计数器,比如设置为5,当每转发一次,这个计数器就减减,以此经过一个路由器就减减、经过一个路由器就减减。所以当路由器转发时识别到8位生存时间为0了,该报文便不再转发,而是直接被丢弃。
16为首部校验和
如果在首部检验的时候,如果检验失败了,那么该IP报文直接被丢弃。
#问:怕不怕一个IP报文被丢弃?
根本不怕,如果一个IP报文出现整体丢失的情况,发送方主机会进行丢包重传(丢包没有ACK然后会超时重传,意味着在TCP中,该数据会一直停留在滑动窗口中)。因为有可能因为一些硬件电路的问题,导致出现一些问题,比如:bit位翻转(0 -> 1,1 -> 0)。
IP地址
在写套接字时,在套接字绑定的时候绑定的是IP地址和端口号。端口号是给传输层用的,IP地址是给网络层用的。
32位源IP地址、 32位目的IP地址,表明的就是数据包从哪来到哪去的问题。我们未来在进行路由转发的时候,每一个路由器都是工作在网络层的。其只要工作在网络层最终其就能够看到交给其的数据包当中的目的IP地址,然后路由器就可以通过目的IP地址来进行数据包转发。
小结
可以发现IP报文的形式与TCP报文的形式非常的类似,也可以发现喜欢叫它们都喜欢叫为:TCP/IP协议。
报头的第二行
知识铺垫
#问:因为链路层有这么一个规定,那如果网络层想向下交付2500字节的数据呢?
因为链路层有这么一个规定,所以网络层就要因为这么一个规定,而网络层就可能要做一件事情 —— 数据分片。
发送端的网络层进行数据分片,接收端的网络层进行数据组装。所以为了支持IP层进行数据的分片和组装,然后才有了报头的第二行所对应的三个字段。
融会贯通的理解:
对应的协议的设计者没有让数据链路层来做数据分片的工作,而是选择让网络层来做这么一个工作,主要原因还是链路层做不到,因为数据链路层会根据底层不同的局域网所采用的技术标准,数据链路层有不同的实现方案:以太网、无线网、令牌环网……。
所以,如果底层的具体的局域网实现是不一样的,那数据链路层它每一层都可能会有存在差异,于是如果我们想将数据的分片与组装放在这么一层,那么就需要实现在不同的网络当中都要完成这个工作,这个成本太高,而且不可控因素太多。
都不如说,反正所有的主机都要用TCP / IP协议,属于操作系统内部,所以数据的分片与组装放在网络层实现,只需要实现一份就够了,岂不乐哉。
#问:网络层需要转发多大的数据是由谁决定的?
网络层没有权利决定自己发送多大的数据,只有传输层由权利决定网络层单次发送数据的大小。
所以:网络层只是干事的!
融会贯通的理解:
数据链路层具有数据包发送大小的限制,其其实不仅仅会影响网络层,其也一定会影响传输层。
在TCP的滑动窗口中就有一个体现,比如:对方主机的接收能力是4096个字节,于是发送方的滑动窗口也是4096个字节。但是并不是将4096个字节封装为一个报文直接进行发送,而是分成多个报文进行发送,这个就与数据链路层的数据包发送大小的限制有关。
#问:什么是分片?
将一个比较大的IP报文,拆分成为多个小的,满足条件的报文。分片的行为是网络层做的,同样的组装行为也必须由接收方的网络层做。
#问:为什么必须由接收方的网络层做?
对方的传输层给其自身的网络层的是一个完整的TCP报文,则接收方,在网络层向上交付给其自身的传输层的数据也必须是一个完整的报文 —— 协议的一致性。
IP报文的分片和组装的行为,TCP是不知道也不关心的,就和公司的老板一样,就需要结果。
#问:分片和组装怎么办到的?
用来填写分片时的相关痕迹 —— 需要在对方的网路层能够足以支撑进行组装。
概念
- 16位标识
ip报文的序号。如果ip报文没有经过分片,那么每一个ip报文的16位标识是完全不一样的。所以就能够在对方的网络层在收到ip报文,根据16位标识的不同,来进行区分所对应的报文的不同。
- 3位标志字段
第一位:保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。
第二位:为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。
第三位:表示“更多分片”,如果报文没有进行分片,则该字段设置为0,如果报文进行了分片,则除了最后一个分片报文设置为0以外,其余分片报文均设置为1。
- 13位片偏移
分片相对于原始数据开始处的偏移,表示当前分片在原数据中的偏移位置,实际偏移的字节数是这个值 × 8 \times 8×8 得到的。因此除了最后一个报文之外,其他报文的长度必须是8的整数倍,否则报文就不连续了。
原理 - 概述
#:分片行为不是主流
在网络通讯里,我们尽量的还是不要让网络层进行分片。
#:具有识别报文和报文的不同
16位的标识,不同的报文,标识不同。相同的报文的分片,标识相同。
#问:标识只有16位,会不会标识不够用?
首先网络的作用是,收到报文就立马向上进行交付。网络层当中是不会出现数据的积压的,有数据就直接向上进行交付,并且交付的过程是很快的,就意味着同时在网络层中存在的数据是不会太多的。
#:具有识别报文是否被分片了
- 被分片了
- 如果更多分片标志位是1,就表明了其被分片。
- 如果更多分片标志位是0,并且13位片偏移(一定)不为0。
- 没有分片
- 如果更多分片标志位是1,并且13位片偏移(一定)为0。
小结:
上述两点,可以使得在收到一批报文的时候,先尽可能的将报文的分片区分出来,并放在一起。
#:识别出哪些分片是开始,哪些分片是中间,哪些分片是结尾
- 开始:更多分片为1,13位片偏移为0。
- 中间:更多分片为1,13位片偏移不为0。
- 后面:更多分片为0,13位片偏移不为0。
#问:中间报文有多个,怎么保切片收全了?
根据偏移量,来进行升序排序,结合偏移量 + 自身大小 = 下一个报文的偏移量,扫描整个报文如果不匹配,中间一定会有丢失的,如果成功计算到结尾,就一定取值完整了。
小结:
上述一点,能够区分是否收全,并提供组装方案。
#:异常处理:任何一个分片的丢失,都可以识别出来
通过上述方法,自然就可以检测出来。
原理 - 具体
- 分片之前,一定是一个独立的ip报文。
- 分片之后,是每一个分片都要有ip报头(为了支持未来的组装,这样才会有对应的报头的第二行)。
(此图省略了报头选项和一些补充数据)
第一个分片的报头是原来报头就有的,后面的报头都是新增的,所以后续的有效载荷组装需要去掉报头。
#:分片是严重不推荐的,分片是具有坏处的
在网络层的分片和组装的过程中,上层的传输层和应用层并不知道,也不关心,上层只知道反正我给你的是一个完整的报文,那么你就要还给我一个完整的报文。
而在网络中丢包是有概率的,而本来就是发送一个报文,然而分成了多个报文,而且对于传输层来说,只有所有的分片报文都存在,这样才是有意义的。而分片相对于是增加的丢包概率的,只要丢掉一个分片报文,网络层就无法将数据进行交付给上层传输层(因为网络层具有校验和),那发送方传输层就只能进行TCP再重传,UDP干脆就没了。
那怎么处理才好?后续再讲解……。
网段划分
知识铺垫
(宏观原理,便于理解,并不是真正的划分)
主流采用的IP地址依旧是IPV4,用32位标识一个主机的唯一性。在整个全球当中,其就如同一个蛋糕一样,在网络刚开始兴起的时候,是首先按照国家 / 地区,将不同种类的IP地址,划分给不同的国家 / 地区。
假设有256个国家:
如此国际间的路由器就只需要根据前8位,如上图:0000 0000就是中国的,然后0000 0000开头的数据包就直接进入中国内部转发。每个国家的IP地址,在开始的时候,就已经被划分好了,国际上的路由器都有自己的路由表,可以进行国家和国家的转发。
以中国为例,中国有23个省,那就以次位的5位表示省份。
然后就如同上述的国家和国家间转发,省份与省份间也有路由器,其就会根据次5位然后进入省份内部进行转发。
然而实际上,每一个国家的经济发展与人口是不一样的,并且每时每秒都是变的,也就代表了入网设备是不一样的。中国内部省份繁荣程度,人口密度也都大不相同,所以这个是需要进行一定的综合评估的。
就是运营商来评估,并且架设路由器,进行IP地址的规划。所以便有了现在主流的网络环境,然后通过一定的IP划分,再通过一定的IP算法 / IP地址架设规则,来进行区域与区域间的转发。所以:我们需要将IP地址进行各种划分,各种网络划分的方案。
子网
- 网络号:保证相互连接的两个网段具有不同的标识 —— 本质上:表征的就是不同的区域。
- 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号。
在进行网络转发的时候,需要先进行利用网络号进行找到目标网络,再根据主机号确认目标主机。
路由器:一定是能够级联两个不同的子网的,这个子网可能是一个国家,可能是一个省,可能是一个市,也可能是一个公司 / 家庭网络。
在进行网络转发的时候,需要先根据网络号先确定区域,然后在区域内部继续根据可能区域内部的方案 / 近一步使用网络号的后半部分进行缩小区域,然后找到目标主机。
网络号是标识网段的重要依据,同一个网络内部大家的网络标识一定是一样的,就按前面的例子来说,中国内部的开始8位就一定是0000 0000。但是主机标识是在同一个网段当中一定是不能一样的。
相同的网段,网络号一定相同,主机号一定不同。不同的网段,网络号一定不同,主机号可能相同。IP = 网络 + 主机,就如同:(学届 + 院系号 + 专业 + 班号) + 学号 —— 学校本身就是一个从上到下的网络结构,当我们希望查找到一位同学的时候,通过前几知道是哪一学届,再次几位找到对应的学院,再次几位找到对应的专业、再次几位找到对应的班级,然后才找到学生。这就是网络在转发的时候,先根据网络号进行转发,最后到达了目标地址,再继续找到主机号。网络号是可以在不同的查找过程中,不断放大,并且收敛。
一个例子:一位计算机学院的学生捡到一张学生卡,他可以知道不是自己班的,于是就向上进行询问(找到对应的层次负责人),然后发现不是本专业、随后不是本院系、不是本学届的,随后就到达学校层次,然后就开始向下根据学号找到丢卡同学,然后将计算机学院的学生的联系方式给丢卡同学,让二者进行联系。
- 捡卡同学:发送数据端;
- 丢卡同学:接收数据端;
- 对应层次的负责人:路由器;
- 负责人所负责的范围:网段;
- 学校层次:公网。
#问:为什么将IP地址划分为网络号和主机号?
- 便于定位。
- 提高查找效率。
- 不同的子网其实就是把网络号相同的主机放到一起。
- 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。
#问: 那么问题来了,手动管理子网内的IP,是一个相当麻烦的事情。
因为当一个新设备的加入是需要分配IP地址,老设备的退出是要回收IP地址。比如说:网络电视打开就需要IP地址,网络电视关闭就不需要IP地址了。而又因为需要进行网路通讯,就一定需要IP地址,没有IP地址就无法进行定位,就没有办法进行可靠转发。
所以当代路由器,为家中提供网络。是路由器对应的营销商将路径为我们配好,而我们使用的时候就是向路由器进行索要IP地址。这种要我们的路由器来进行自动回收和分配等管路行为的IP技术叫做DHCP。
- DHCP能够自动的给子网内新增主机节点分配IP地址,避免了手动管理IP的不便。
- 一般的路由器都带有DHCP功能,因此路由器也可以看做一个DHCP服务器。
概念
过去曾经提出一种划分网络号和主机号的方案 - 分类划分法,把所有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
- 例如:申请了一个B类地址,理论上一个子网内能允许6万5千多个主机,A类地址的子网内的主机数更多,然而实际网络架设中,不会存在一个子网内有这么多主机的情况,因此大量的IP地址都被浪费掉了。
- 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号。
- 子网掩码也是一个32位的正整数,通常用一串 "0" 来结尾。
- 将IP地址和子网掩码进行 "按位与" 操作,得到的结果就是网络号。
- 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关。
利用掩码左半部分全1,按位与提取出对应的IP地址的到网络号,剩下的用户未来的提取,就是主机号。
这样就可以通过给不同的路由器配置不同位数的子网掩码,就能够看到不同的网络号。以此通过改变看到的网络号的 "长度" 不断变大(因为子网掩码不断变长),也意味着主机号越来越收敛("长度" 不断变短)。
所以给对应的IP配置子网掩码,将来就可以:目的IP & 当前路由器的子网掩码 = 该报文要去的目的网络。因为不同的路由器一定至少要级联2个网络,且每一个网络的网络号可能是不同的,所以每一个路由器也有自己直接连接的网络配置的对应的子网掩码。
特殊的IP地址
- 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网。
- 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包。
- 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1。
IP地址的数量限制
我们知道,IP地址(IPv4)是一个4字节32位的正整数。那么一共只有 2的32次方 个IP地址,大概是43亿左右,而TCP/IP协议规定,每个主机都需要有一个IP地址。
#问:这意味着明明就完全不够使用,一共只有43亿台主机能接入网络么?
- 动态分配IP地址:只给接入网络的设备分配IP地址,因此同一个MAC地址的设备,每次接入互联网中,得到的IP地址不一定是相同的。
- NAT技术(后面会重点介绍)。
- IPv6:IPv6并不是IPv4的简单升级版,这是互不相干的两个协议,彼此并不兼容。IPv6用16字节128位来表示一个IP地址,但是目前IPv6还没有普及(网络是底层的,需要将所有的操作系统内核换一下)。
私有IP地址和公网IP地址
如果一个组织(区域 / 公司 / 高校 / 家)内部组建局域网,那么有一类IP地址是只能用于局域网内的通信,而不直接连到Internet(不能出现在公网)上,理论上使用任意的IP地址都可以,但是 RFC 1918 规定了用于组建局域网的私有IP地址。
- 10.*,前8位是网络号,共16777216个地址。
- 172.16.到172.31.,前12位是网络号,共1048576个地址。
- 192.168.*,前16位是网络号,共65536个地址。
- 包含在这个范围中的,都成为私有IP,其余的则称为全局IP(或公网IP)。
所以,IP地址被分为了私有IP地址和公网IP地址。
#问:为什么要这么分?这两套网络体系是如何进行的通讯?
查看windows的IP地址:
1. 使用cmd打开命令行操作窗口。
2. 使用ipdonfig命令查看。
此处本人使用的无线网,所以是无线局域网适配器,在里面可以发现IPV4地址以及,子网掩码,默认网关。从子网掩码可以说明,网络号就是192.168.1,而所谓的默认网关就是我们所对应的路由器,一般默认网关是我们的特定子网当中的第一台主机,所以其主机号为1。因为路由器首先是要先构建网络,所以第一台路由器就是先入网的,所以IP地址一般都是当前局域网的第一台主机。
我们可以看到192.168.*,前16位是网络号,共65536个地址。这也就是为什么我们查我们的IP地址全部几乎都是192.168.*的原因,因为我们用的都是局域网 / 私有网络。如果有云服务器的可以查,几乎都是172.16.到172.31.,前12位是网络号,共1048576个地址。
而如果是虚拟机,并且虚拟机的网络连接方式是 NAT模式 的话,查IP地址几乎都是10.*,前8位是网络号,共16777216个地址。
换句话说,就是现在我们直接接触到的根本就不是公网IP,而是私网IP。
#问:我们在家里需要进行上网,我们会先做什么?
- 有运营商在家附近进行了网络的覆盖。
- 联系运营商进行光纤入户。
- 工作人员上门,调制解调器(猫),可能赠送无线路由器。
- 开户:账号、密码,配置路由器(该账号、密码用于运营商认证)。
- 配置路由器:设置路由器wifi名称 + 密码(该密码用于路由器认证)。
- 正常上网,正常缴费。
#:像如华为一样的通讯厂商与运营商的关系。
可以简单的理解为:运营商是做方案的,是做具体落地的(将网络铺设在什么地方,覆盖面要多大,光纤要怎么埋),而运营商需要的各种各样的设备:路由器交换机、网线、各种服务器……通讯相关的设备,是由如华为一样的通讯厂商提供的。
#问:我们玩抖音、微信、头条、搜索、外卖……,可是到了月底,话费却给了运营商,为什么?
我们在入网时候,看起来好像是在上网刷抖音等,进入的是互联网公司,实际上是我们先将将数据请求发送到运营商那里,然后由运营商基站、网线、交换机等,来将我们的数据请求推送到特定的互联网公司所匹配的提供服务的机房,硬件上到达机房之后,软件上再开始进行数据包的向上交付,到达服务的进程,然后为我们提供服务。因为,基础设施是运营商铺设的,就如同高速公路的收费。
#问:初步理解一下,我们经常听到的,我们是访问不了goole、Facebook等等网站的,为什么?
都知道我们国家是有墙的,运营商设置的,简单来说就是这路行不通。无论是手机,还是家里的路由器是都有账号的,并且是运营商所知道的。所以有了账号运营商就能认证我们,看在各方因素都合格的情况下,才会进行发送。如余额流量不足,报文直接就丢弃,UDP就直接没了,TCP就多次重传,然后发现都没有任何应答,于是判断网络阻塞,然后判断网络有问题。
同理的,在发送的IP地址是国外的IP地址的时候就直接拦截我们,也就是直接丢弃我们的报文。
#问:如何凸显是运营商将我们的欠费的报文丢弃的?
在日常生活中,我们一旦欠了费,我们无法给他人拨打电话,但是我们可以给10086拨打电话。
私网里面的所有IP地址都叫做内网IP。所以在我们的数据包没有被发送到公网之前,其实我们所有的报文在转发时都是在从一个子网跳到另一个子网的过程,用的全部都是私有IP。
私有网络对应的IP是局部的,可以在不同的子网中出现重复。于是,IP不足的问题就大大的缓解了。比如中国有23个省,如此每一个区域都可以是一个大型的局域网,大型局域网中,所有人用的私有IP全部都可以是一样的,这样就相当于我们让入网的设备大大的增加,但是消耗IP地址的只有公网当中会消耗对应的IP地址。
#问:万一私网中的IP地址不够使用了呢?
没有任何问题,那就再下放一个公网IP,然后再继续将网络拆成两个不同的子网,然后这两个子网再使用同样的IP地址。
然而,正是IPV4这样的策略,所以这也就是IPV6难推的原因,IPV4这样的通过不断的推公网让子网出现重复,于是IPV4能解决,就成为了推行IPV6阻碍。
#:家用路由器
- 对内:面对自己构建的子网。
- 对外:自己本身也是别人构建子网的一个主机。
#:决定了路由器一定要有两套地址
- 对内:Lan口IP,局域网IP。
- 对外:WAN口IP,自己所在上级子网给自己分配的IP。
#问:如何进行的数据包传送?
报文推送(NAT技术)
首先让我们看看向外推送,这个时候没有任何问题,找到对应的公网IP就就行了,很简单。
但是,如果是这样的方式进行推送,再先将对应的应答数据推送回的时候就会很尴尬,因为目标IP地址将变为私有IP,而公网根本就不认识私网IP(路由器查找上找不到),因为私有IP不会出现在公网上。并且全国有很多的同样IP的地址,目标IP地址(私有IP)并不具备唯一性,无法进行向回推送。
所以之前的向外推送,只是宏观上,其实细节上,路由器需要做一个事情:将报文中的源IP替换成路由器的WAN口IP,并且经过的每一个运营商的内网路由器,都要做这个工作(公网路由器不需要做)。
所以,站在运营商的路由器来看,其认为该报文是家用路由器给的。站在家用路由器来看,其认为该报文是一个主机给的。而在百度的服务器看来,这个报文的IP就是公网(运营商的路由器WAN口IP),而公网是可以与公网进行通讯的。
(如何内网转回,后续讲解……)
这种源IP地址在不同内网中,不同层级的网络节点中转发,被替换的技术叫做:NAT技术(Network Address Translation,网络地址转化)。
融汇贯通的理解:
所以实际上运营商做的工作,除了简单的报文转发之外,还在转发的时候可以对我们的数据进行合法性的验证(如:报文是否有非法的内容),如果非法就可以对报文进行拦截、丢弃。当然如此运营商也可以干一些坏事情。如,Https协议中讲到的一种攻击方式:中间人,相对于来说运营商做中间人是十分的简单的,所以Http下的访问连接被更改也是很容易的,毕竟源IP都能被换掉,那数据中的下载连接换掉何尝做不到。
- 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点。这样的运营商路由器可能会有很多级,最外层的运营商路由器,WAN口IP就是一个公网IP了。
- 子网内的主机需要和外网进行通信时,路由器将IP首部中的IP地址进行替换(替换成WAN口IP),这样逐级替换,最终数据包中的IP地址成为一个公网IP。这种技术称为NAT(Network Address Translation,网络地址转换)。
- 如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有外网IP的服务器上。这样的服务器可以在阿里云 / 腾讯云上进行购买。
路由
在复杂的网络结构中,找出一条通往终点的路线。路由的过程,就是这样一跳一跳(Hop by Hop)"问路" 的过程。所谓 "一跳" 就是数据链路层中的一个区间,具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间。
也就是路劲选择的问题,问题是跳往的是哪一个路由器,这个路由器的选择,就是和路由表的算法有关系的,也是子网划分设置好的,是:子网划分 + 路由表 = 一整套的路由转换方案。
- 当IP数据包,到达路由器时,路由器会先查看目的IP。
- 路由器决定这个数据包是能直接发送给目标主机,还是需要发送给下一个路由器。
- 依次反复,一直到达目标IP地址。
不可能出现路由器查了查然后不知道下一步怎么走,因为这样的路由器是不允许存在的,这个这个路由器是有BUG的(该路由器内算法有问题)。
#问: 那么如何判定当前这个数据包该发送到哪里呢?
- 路由表可以使用route命令查看。
每一个设备,其只要工作在网络层之上,那都必须维护一个路由表。
Flags:U标志表示正在被使用,G标志表示是一个默认网关 / 路由器。
Iface:代表的是发送接口。
- 如果目的IP命中了路由表,就直接转发即可。
- 路由表中的最后一行,主要由下一跳地址和发送接口两部分组成,当目的地址与路由表中其它行都不匹配时,就按缺省路由条目规定的接口发送到下一跳地址。
说白了就是,当收到一个报文,(根据从上到下)依次拿该报文和子网掩码按位与,以此得到的报文的目的网络,然后将结果与子网掩码对应的目的网络地址Destination进行比对,如果相等就直接通过Iface代表的发送接口,发送出去(说明该数据包下一跳就应该跳去对应的子网)。eth0就是我们在对应的网络方式中所对应的网路转发接口。
如果将该数据包的目的IP地址与子网掩码进行“按位与”后,没有找到匹配的目的网络地址,此时路由器就会将这个数据包发送到默认路由,也就是路由表中目标网络地址中的default。可以看到默认路由对应的Flags是UG,实际就是将该数据转给了另一台路由器,让该数据在另一台路由器继续进行路由。
路由器的查找结果可能有以下两种:
- 路由表查询后(查得到):得知该数据下一跳应该跳到哪一个子网。
- 路由表查询后(查不到):没有发现匹配的子网,此时路由器会将该数据转发给默认路由。
假设某主机上的网络接口配置和路由表如下:
转发过程例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地址是以地区进行的划分,但是实际的情况是更加的复杂的多的多(因为网络不是均分的,而是按照分类的方式进行划分的,所以网路是一个非常复杂的拓扑结构)。
总结
TCP协议:帮我们解决的可靠性问题,但是并不是做实际的数据转发的(明显路由器就没有传输层)。
IP协议:提供一种能力,将数据从A主机送到B主机的能力。
所以正真的网络环境是:
于是TCP/IP协议便可以可靠的将数据从A主机送到B主机。
其在做转发的时候是根据:
- 目的IP
- 子网划分
- 路由表查找与路由算法
然后,最终以跨网络的方式将数据从主机B送到主机C。可是想通过以路径选择的方式将数据送到主机C,首先就要解决数据从主机B到路由器F,然后再解决路由器F到路由器G,以此一路到主机C。所以再回头看,IP协议其实并没有解决设备转发的具体功能实现,IP提供的是转发的策略。
实际上是主机B的数据经过决策发现需要发送到路由器F,所以IP协议的核心工作根本就不是转发,而是做路径选择,实际上IP协议没有能力将报数据包扔出(没有办法将数据直接通过网络层,扔到对方的网络层),而必须将数据交付给下一层。
所以更深的解决就是局域网转发的问题,由下层解决。