网络层——IP协议

在TCP/IP四层协议中,TCP协议也叫做传输控制协议,它的作用是当应
用层发送数据到对端主机时,TCP协议来决定什么时候发,发多少,以
及出错了怎么办的一系列问题。我们可以看到TCP协议更多的是注重进
行网络通信的两台主机,但是我们知道实际上的网络通信,可不单单只
与两台机器有关系,我们还有网线、有路由器等等一系列网络基础设施
以及下层网络协议共同构成庞大的网络世界,所以我们想要真正的认识
网络世界,单单一个TCP协议是不够的,那么我们就来认识网络世界中
另一个比较有代表性的网络协议——IP协议。

  首先我们要清楚,IP协议所处的位置在哪里?下图是TCP/IP协议四层协议模型:
在这里插入图片描述
  在应用层中我们认识了HTTP、HTTPS等具有代表性的应用层协议,在传输层中认识了TCP、UDP协议,而IP协议则处于网络层,除IP协议之外,网络层中还有其他协议(后面会简单介绍),但是网络层中最具有代表性的协议那就是IP协议了,在上两层网络协议的认识中我们对网络通信的认识一般是这样的:
在这里插入图片描述
  在逻辑上我们可以认为,数据是直接从主机A的传输层到达了主机B的传输层中,可是实际情况上我们是忽略了网络协议中更为底层的协议,并且我们忽略了数据传输时两台主机之间的事物。这导致我们对网络的认识是不全面的,也说明了网络并不单单指互相通信的两台机器,除此之外还有更多的东西等着我们去认识。

1. 认识IP协议的作用

接下来我贴上一张将注重于网络数据在两台机器外的传输的一张草图:
在这里插入图片描述
  这就是在计算机之外,一个报文所要经过的一系列设备,这里我们要知道一些名词,在报文从一个设备到下一个设备时,这个下一个设备叫做下一跳,而上图中无论是主机还是路由器其实都可以被当作主机
  我们看到在现实生活中,当一个报文被发送出主机后,并不是直接到达目标主机,而是还要经过中间很多的网络设备,也就是路由器,这些路由器起到了路由的作用,并且我们也发现在现实生活中主机与主机之间相连构成了复杂的拓扑结构,那么问题就来了,在报文送到主机C的过程中,为什么报文在经过路由器B之后要去路由器C呢?为什么不去路由器G呢?我们就知道了,报文在网络传输的过程中是需要路径选择的功能的,而这个功能我们在应用层和传输层上都没有体现过,而这就是IP协议的作用。
  在这里我直接给出结论:IP协议在网络报文传输过程中提供了将报文从一端主机到另一端主机的能力。
  更具上面的那句话我们要认识到一个事情,一个人据有完成某件事的能力就一定会在做那件事时完成它吗?答案是不一定的,所以IP协议提供了报文从一段主机到另一端主机能力,但是它不是百分百的能够完成这件事情,我们要有着这样的认识。而也正是IP协议有着这样的不完善,所以才有了我们的传输层中可靠的TCP协议。IP协议负责将报文从一段主机送到目标主机,而IP协议+TCP协议负责可靠的将报文从一端主机送到另一端主机,两者缺一不可。这也就是为什么TCP/IP协议四层模型以他俩命名的,我们发现将数据从一端可靠的送到另一端这不就是网络最根本的的作用吗?

2. 知识铺垫

  在上面认识了IP协议的作用之后,我们还需要在正式认识IP协议之前,铺垫一些知识。

a. 网络号和主机号

  在我们以往对IP地址的认识就是把他简单的认作是一个四字节的序列,但是其实,IP地址的字节序列被分为两个部分一部分是网络号,另一部分是主机号
  这就像我们去一个地方旅游参观一个地方一样,就比如我们去参观故宫,我们应该是先去北京,然后在去故宫,不是直接去故宫。
  而报文的传输也是这样,在上图中我们并没有突出子网的概念,其实我们每个上网的主机,必定是处于某一个子网中的
在这里插入图片描述

  图中的大蓝色圆圈我们可以认为就是一个子网,小的黑色圆圈就是处于子网中的其他主机。报文的传输其实就是从一个子网到另一个子网中,而在子网之间的传输需要的就是网络号,而到达目标子网之后我们会根据主机号找到目标主机。

b. 网络世界的背景

  我们平时在家里可以上网的原因是因为家里面有路由器,并且从外面来回来网线,然后给运营商缴费之后,我们就可以正常上网了。但是在有了上面的认识之后我们发现除了我们家里的路由器之外,外面竟然还有许多的路由器,并且我们上网是需要缴费的,这些事情说明我们现在所处于的网络世界不是凭空产生的。
  所以要认识网络世界,我们也必须要有这样的认识:网络不是凭空产生的,它的出现是有人精心设计过的,而在我们国家它指的就是运营商。所以要认识网络世界我们应该也要认清运营商在网络世界中的定位是什么样子的,关于这个话题,我们之后会再谈。

3. IP报文格式

  接下来我们直接认识IP报文的格式:
在这里插入图片描述
  在认识一个协议的报文格式的时候我们总要注意两点:如何将该报文的有效载荷和报头分开?如何将有效载荷向上交付?
  那么在IP协议的报文中,我们可以发现除选项字段和数据字段外,IP报文的长度是固定的20字节,并且在这二十个字节中,有两个字段,一个是4位首部长度,一个是16位总长度。4位首部长度在TCP协议中我们就已经认识了,它用来表示IP报文报头的长度,单位是4字节,范围是[0, 15] * 4 ==> [0, 60]。而16位总长度则是表示整个报文的长度,那么根据这三个认识,我们首先对获得的报文截取它前二十个字节,然后找到4位首部长度就可以将报头和有效载荷分离了。
  而关于想上交付的问题,IP报文中有一个字段叫做8位协议的字段。而关于这个字段的作用我们首先要认识到,当两端主机在网络上进行数据传输时,在传输层中,两端使用的协议必须是一致的。在这个认识下,发送方会在它的IP报文中的8位协议中明确传输层使用的是什么协议,在对端主机收到该IP报文之后就会识别该字段中的信息,就会知道要将该报文向上分配给哪种协议了,向上分用的问题也解决了。
  接下来我们要认识的是4位版本,这个字段一般都是默认填4,以表示我们使用的IP协议版本是IPv4版本。那么现在就有人有疑问了,我以前好像在哪里见过还有一个叫做IPv6的版本,那这里填成6是不是就代表使用的IP协议版本就是IPv6了?其实不是的,IPv6虽然和IPv4就差了一个数字,但是这两个协议是不兼容的,如果对IPv6有兴趣的话可以自行去了解。
  接下来是8位服务类型,关于这个字段我们也是稍作了解即可:8位服务类型(Type Of Service): 3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0). 4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本. 这四者相互冲突, 只能选择一个. 对于ssh/telnet这样的应用程序, 最小延时比较重要; 对于ftp这样的程序, 最大吞吐量比较重要。
  接下来是8位生存时间(TTL),关于这个字段的认识我们又要回归到上面那张图了:
在这里插入图片描述
在报文传输的过程中,可能会出现如上图的情况,报文一直循环在几个路由器中而无法到达目标主机(尽管这样的概率很小)。但是一旦出现这样的情况,我们要知道在网络传输中可不止传输一个报文,那么随之时间的推移,越来越多的报文积聚在这几个路由器中,势必会导致网络传输的速度变慢出现拥塞的情况。所以面对这种情况报文就有了生存时间,这个生存时间就是相当于自己经过的跳数。每经过一跳,这个字段就减减,等到这个字段为零时,那么接收到该报文的节点则会自动丢弃这个报文。
  在IP报文剩下的字段中,选项不谈,32位的源IP目的IP不用多说,16位首部校验和,我们发现它是首部校验和,而不是校验和。这是因为在将报文向上分用到传输层后,传输层的协议会对报文做校验,至于IP协议只需要对自己的报头进行校验即可。16位标识、3位标志、13位片偏移我会在较后面再讨论。
  这就是目前我们对IP报文头格式的认识。

报文的封装与传递

  在认识TCP协议的过程中我们大概了解了sk_buff的大致结构,知道它维护着一段缓冲区,缓冲区中存放的就是报文,而现在简单认识IP协议之后我们可以讨论一下,报文是如何在协议之中逐层传递的:
在这里插入图片描述
  这就是大致的报文交给下层协议的大致过程,在这其中我们要注意其中四个字段那就是:tail指向的是缓冲区中报文结尾的位置,而end指向的是尾部空间结尾的位置,需要注意的是尾部空间之后缓冲区仍然有空间,head则指向缓冲区的开始,而data字段则指向报文的开始,可以看到的是,当报文从结构体向下层传递,IP协议封装好报头之后,data指针也同样偏移了。还要知道的是sk_buff结构体中是自带链式结构字段的,所以,报文在协议之间的传递其实相当于就是在各个链式结构中增删而已:
在这里插入图片描述
在这里插入图片描述

4. 网段划分

a. 网络号和主机号

  在上面的讨论过程中我们提前已经认识到了网络号和主机号的大概作用,接下来我们会更进一步的认识它:
在这里插入图片描述
  如图我们看到的是两个子网,并且这两个子网中间又由路由器进行连接。并且由黑框和红框组合起来的一串数字我们不难发现它就是各个主机的IP地址,而其中黑框框住的部分就是网络号,红框框住的就是主机号。网络号在同一子网内是相同的,不同子网的网络号是不相同的。但是主机号不一样,在子网中,各个主机的主机号是不相同的,但是不同子网中的主机号是有可能能相同的。需要注意的是网络号的说法我们限定的情景是公网(公网和子网后面会详细说到)
  并且我们看到路由器携带两个IP地址,这也说明路由器内部一般是有两张网卡的。而且在一个子网中,路由器的主机号一般是1。
  通过这张图我们还可以看到每个IP地址后面都有一个斜杠加数字,这个数字目前表示的就是IP地址的前多少位是被代表作网络号,那么呼之欲出的就是除在该数字位数之后的位数,则表示主机号。
  上面我介绍了这张图中的一些细节,并且也再一次加深了我们对网络号和主机号的认识,但是在这张图的背后我们还需要有更多的认识和结论。
  我们在家里面假如想刷刷短视频、打打游戏时,我们需要先联网,这是因为我们没有IP地址,从而导致我们无法上网,那么当我们通过有线或无线的方式连接路由器之后,我们就可以正常上网了。这是因为路由器给了我们一个IP地址,从这里我们可以得出:路由器有着构建子网的功能。当我们连上网之后,路由器给我们分配了一个IP地址。这也说明着路由器在子网中有着管理IP地址的功能,其实这个管理IP地址的服务就工作在路由器的应用层,叫做DHCP。有些人就有疑问了,路由器不是最高才到网络层么,为什么还会有应用层的出现啊?我们在这里要认识一点,那就是当你查看自己家的路由器的背面会发现会有一个用户名和密码,还有一个IP地址,当你使用浏览器访问路由器背面的IP地址的时候,会出现一个网页,它会让你输入用户名和密码,登入之后你可以设置该路由器的一些设置,这也说明现在的路由器还有Web服务,所以又多了一个DHCP也不足为奇了。
  还有一点,那就是假如把上图中的上面的子网作为我们的家庭网络,那么下面的子网一般就代表着运营商的子网,这也更加说明了运营商在网络世界中的地位,这也为我们之后正式的认识运营商做了一点铺垫。

b. 网段划分

  我们知道IP地址是一个四字节序列,它可以表示的IP地址数量大致就有四十多亿,随着网络的发展,从简单的局域网到公网,使用网络的人也越来越多,他们所代表的身份也各有不同有的代表企业,有的代表政府,有的代表其他组织,所以IP地址就被分为了五种类型:
在这里插入图片描述
  在IP地址被分类之后,A类网络在子网中可以搭建的主机数量是2^24个,但是在现实生活中根本不存在一个子网中有如此多的主机,这样就导致了IP地址的浪费,这就导致大部分人都申请B类网络,导致B类网络很快被申请完,导致出现IP地址不足的问题。
  那么基于这样的情况就提出了新的划分方案,被叫做CIDR。它引入了一个叫做子网掩码的概念,这个子网掩码同样也是一个32位的序列,通常以一串一开始,以一串零结束。通过子网掩码与IP地址按位与之后得到的序列就是网络号,而IP地址剩下的序列就是主机号,这么看着好像有一点眼熟,这就是上面我们所谈论主机号与网络号时斜杠后的数字,那个数字是代表子网掩码的前多少位为1的意思,而这也是子网掩码的一般表示方式。
  在有了子网掩码之后,网络划分就与这个网络是A类还是B类、C类无关了。
  我们可以现在就看看子网掩码的功能,假设现在我们申请了一个B类网络,我们要组建自己的子网,那么会得到如下结果:
在这里插入图片描述
此时我们的IP地址分布是这样的:
在这里插入图片描述
  然而主机数此时就有2^16个仍然有一点多,这样就会导致该网络号中的主机号被浪费,而引入子网掩码之后,我们可以将该网络继续划分子网:
在这里插入图片描述
  这样的话我们可以使用子网划分,只是用其中一部分的IP地址,而保留剩下的IP地址可以用做划分其他子网,这样就会提高我们对IP地址的利用率。而这也是子网掩码的作用。它虽然没有让IP地址的绝对数量上升,但是它提高了IP地址的利用率,缓解了IP地址不足的问题。
  需要注意的是,上面的申请网络这种行为,我们好像没有听说,其实这是正常的,这是因为申请IP地址这种行为一般是由运营商来完成的,所以我们再一次见到了运营商子网络世界中的地位,既然他可以申请IP地址,那么子网划分的工作也是由他来完成。更加需要注意的是,我在上面子网划分中谈及到的的网络都是公网

c. 为什么要进行网段划分

  关于这个问题的回答,我们只需要举一个例子即可:
  假设在一所大学中,每个学生的学号由如下结构构成:
  院号 + 专业号 + 班级号 + 个人编号比如010101。
  该学校有若干学院,并且每个学院都有一位代表比如院学生会主席,而在这些院学生会主席中还有一个人兼校学生会主席。在机械学院有一位同学叫小明,在数学学院有一位同学叫小红。
  有一天,小明在路上走着,忽然看到一张掉在路上的学生卡,而这张学生卡上的数据都有点模糊了,只能看清一串学号。小明此时也想将这张卡物归原主。
  而如果没有上面学号构成的设定的话,小明为了找到这张卡的主人只能一个一个问碰到的同学,在计算机中,那么这种时间复杂度是O(N)。
  而如果有了上面学号的设定的话,小明看到入学年份后面的院系代码跟自己的不一样,那么他就会意识到这张卡的主人不是本学院的,他直接把卡交给自己的院学生会主席,院学生会主席一看院系代码就知道这位同学是数学学院的,所以他就交给了数学学院的学生会主席,数学学院学生会主席收到卡之后,一看专业号,再看班级号一下就能知道这张卡就是小红的卡,这样小红就收到自己的卡了。
  在这个归还卡的过程中,时间复杂度是O(1)。
  网段划分亦是如此,不在目标网络时,目的IP地址会一直与子网中的网络号按位与直到两者的网络号相同找到该子网,这样的话再根据主机号就可以定位到目标主机,将报文传递给目标主机。
  网段划分的一个作用的就是提高了网络传输的效率

d. 仍然存在的问题

尽管上面提出了子网掩码的技术,提高了IP地址的利用率,但是仍然没有增加IP地址的数量,面对发展迅猛的网络世界,IP地址的数量还是不够用的,所以这时候就有了新的解决办法,而这个解决方法又与公网和私网有关。在上面讨论的过程中我的话语中或多或少提及公网,子网,私网等字眼。其实IP地址还被分为了两部分,那就是公有IP和私有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组成(当然还有一些特殊的IP地址)。

c. 特殊的IP地址

  在四十多亿的IP地址中有一些地址是较为特殊的地址:

将IP地址中的主机地址全部设为0, 就成为了网络号, 代表这个局域网;
将IP地址中的主机地址全部设为1, 就成为了广播地址, 用于给同一个
链路中相互连接的所有主机发送数据包;
127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1;

  以上就是网段划分的大致内容。

5. 运营商

  在上面的一系列话题中,我曾数次提到运营商这个角色,因为他对于网络世界的发展起着非常重要的作用,并且有着特殊的地位。
  在几年前或者十几年前,互联网还不是特别遍及的时代,我们的县城中或者镇子中通常会有一些运营商的门店,这些门店中的人员一部分工作是买电话卡,还有一个很重要的工作就是,给需要的家庭安装宽带服务,并且有些工作人员会直接登门拜访到你家,问你需不需要宽带服务,如果需要的话我们会送你一部手机并且还有一张电话卡,路由器,调制解调器等上网需要的设备,将来需要交网费的时候,你往这张电话卡中充钱就可以了。那如果你需要宽带服务的话,装修宽带的师傅,就会从外面的一个携带运营商标志的盒子中,拉出一根网线来,然后接入到你家路由器中再进行相关工作之并且你交上网费之后,你就可以正常的上网了。
  上面的实现一个家庭的上网过程好像不是那么复杂,但是网络的普及真的这么简单吗?
  如果有人曾经关心过国内企业向海外发展的话,大多数情况都不是还互联网企业先发展到海外,而是一些比较处于硬件层面的企业先过去,比如手机,当然还有一个重要的企业那就是运营商,如果国内运营商不向海外发展的话,国内互联网的产品发展到海外是比较麻烦的。
  那么运营商向海外发展的过程,不就是曾经我们本地网络发展的过程吗,在网络发展的过程中,首先需要挖地铺设光缆,建设基站等等一系列费力的工作,而当这个工作做完之后,才能有宽带安装师傅拉一根线到你家,再经过简单的操作之后就可以上网了。所以运营商对于网络的发展是起到非常重要的作用的,这种现象不论国内国外都是一样的,网络要发展,首先就得干这些苦活累活。
  所以一般在现实生活中,我们的网络大致是长这样的:
在这里插入图片描述
  而也正是这样的结构,当我们向互联网公司发送请求时,首先是会发送到运营商的网络中,然后再由运营商发送到对应的互联网公司的网络中。
  这也会使得我们在网络上下载东西的时候有时候会突然下载到一些其他互联网公司的产品,这其中发生的url劫持事件有一部分就是运营商做的,这也说明运营商可以识别你向互联网中发送的信息,并且识别到某些特定信息,转变你的请求。既然可以转变,那也意味着可以阻断,而这也是我们无法正常使用谷歌浏览器的原因。
  所以在了解过上面运营商的身份之后我们,我们要知道两件事情,为什么我们在上网看短视频使用的是互联网厂商的APP时,但是上网的费用却交给了运营商,是因为互联网企业也得通过运营商的网络再将数据交给用户。
  并且我们现在知道其实我们的家用路由器是横跨了两个网络的。

6. 报文在网络中的传递

  在上面认识过网段划分以及运营商的身份定位之后,我们现在来继续认识一个报文在网络世界中是如何传递的,我们首先先附上一张大致的网络拓扑结构的图:
在这里插入图片描述

  我们可以看到路由器中有两个地址,上面我们也知道路由器一般连接两个子网,所以有两个IP地址很正常,以192开头的子网为主导的话,那么其中路由器中192.168.1.1叫做LAN口IP,而10.2.3.11就是WAN口IP,也就是在一个局域网中,跟本局域网网络号相同的路由器上的IP地址叫LAN口IP,另一个就是WAN口IP。
  又有着上面对运营商的认识,以192.168.1开头的这几个局域网一般都是家庭网络,再往外走10.2.3.1这个就是运营商的2网络(也是私网),再向外才是广域网也就是公网。我们的网络世界是由公网和私网(运营商构建的子网和家用网络)所组成的。
  那么现在我们假如要从家庭一中发送一个报文到互联网公司的话,我们的IP报文的源IP地址和目的IP地址应该是src:192.168.1.23,dest:2.3.4.7。我们拿着这个目的IP地址在本局域网中通过子网掩码一对比发现不在本网络中,所以这个报文会发送给本网络中的路由器1,让路由器1向外发送到WAN口IP对应的子网中,然后再次进行目的IP地址与所处子网的网络号进行对比,发现还不是那么继续向该子网中的负责向外连接的路由器传递该报文,现在我们到了网络号为2.3.4.0的子网中,对比网络号,网络号对上了,然后就直接将该报文发送到对应主机号的互联网公司中。
  上面的陈述好像看似正确,但是假如我们这个报文的内容是一个拉取视频的请求,这时就需要互联网公司给我们也发送报文,而互联网接收的报文中源IP地址是192.168.1.23。互联网公司将此IP地址作为目的IP封装好报文发送出去,结果这个报文找不到回来的路了,因为这个报文直接发送到公网上,已经是最外层的网络了。所以说上面报文从家用网络到互联网公司的方式是不对的。
在这里插入图片描述

  所以私网IP是不允许出现在公网的,正确的报文发送是当内网向外网发送报文时,该报文的源IP地址要进行替换
  而替换的方法也就是将源IP地址换做出口路由器的WAN口IP:
在这里插入图片描述
  这才是一个IP报文进行跨网络发送的正确形式,而这种报文进入到外网进行源IP地址切换的技术叫做NAT技术
  经过这样的网络发送,当互联网公司要响应该报文的时候,起码是可以找到发起者的公网上的入口路由器,而至于报文怎么回到家庭一我会在后面继续阐述:
在这里插入图片描述
  有了上面发送报文的知识之后,我们又得出了几个结论:
私网IP地址不能出现在公网上,所以导致私网IP地址是可以重复的
  现在有一个问题:家庭一和家庭三之间可以直接进行网络通信吗?
目前来看我们是做不到的,因为我们的目标IP地址是一个私网地址,由于私网地址不能出现在公网中,并且私网地址可以重复,我们是找不到该IP地址的。
  我们的家庭网络出去之后不一定就是公网

子网掩码

  子网掩码,我们在Windows机器上可以在命令上输入ipconfig查看子网掩码:
在这里插入图片描述
  在Linux中则输入ifconfig查看子网掩码。
在这里插入图片描述

较为全面的认识网络拓扑结构

  在上面我们知道了一个报文发出后如何到达它的目的地(至于如何回来,我会在我的下一篇文章继续阐述),接下来我将较为全面的介绍世界上的大致的网络拓扑结构,加深我们对网络世界的认识。
  我们现在就对这个世界进行一下子网划分:
  世界上差不多有二百个主权国家,我们就使用IP地址的前八位来区分这些国家(实际上这样的IP地址的分配方式是不对的,关于IP地址的分配有着更加复杂的方式):
在这里插入图片描述
  然后我们再在我们的国家进行子网划分,我们的国家有34个省,所以我们使用6位二进制就可以表示全部的省份了:
在这里插入图片描述
  然后省的下面有若干市,以山东为例,山东有14个市区,我们再使用6位二进制来表示全部市区:
在这里插入图片描述
  这样呢,一个市区就也被划分好了,再往下呢可能还是公网,但是我们就不再往下使用公网划分了,我们就该进入运营商的子网以及家庭网络了:
在这里插入图片描述
  那么假如现在远在美国发送出一条报文,它的目的IP地址是1开头的,那么它首先再自己国家的网络中逐层进行网络号的对比,发现都不匹配,而一直到了国际路由器组成的网络中,才知道这个报文目的地是中国,所以就发往中国的子网中,然后再继续寻找目标网络以及主机了。
  我们在山东发送一条报文,它的目标IP地址是1.8.x.x那么我们首先会在自己家庭网络进行网络号对比,不匹配然后再在运营商的子网中进行网络对比,也不匹配,知道这个报文进入省份之间的网络中,才知道它的目的地是去山西,那么它就会再进入山西的网络中继续寻找。
  而我上面所说的从市区网络上到国家之间得整个网络结构就是公网了。
  而互联网公司也申请这样的公网IP,然后像上面的市或省一样接入对应的子网结构,那么我们也就能访问互联网公司了。

7. 路由表

  到现在我们已经清楚了,一个报文的发送以及较为全面的网络拓扑结构,但是我们仍然会有问题,那就是在上面的报文转发过程中,主机好像天然的就知道,这个报文经过判断之后该往哪里发,比如该报文的目的地不在本网络中需要向外发送,又或者是该报文的目的地就在本网络中。这个判断的过程真的是天然的吗?答案肯定是错误的,因为网络世界是被人精心策划过的,那么这个所谓的“天然的”现象一定不天然,其实这个判断的依据,是因为我们的主机中在网络建立好的时候,子网中各个设备就会交换数据形成一张路由表,而报文发送到哪里依据就是这张路由表,在Linux系统中,我们可以使用route命令来查看路由表:
在这里插入图片描述

在这里插入图片描述
  其中的-n选项就像我们使用netstat命令一样都是让本来可以显示数字的地方显示数字。
  其中Destination代表目的网络IP地址,而Gateway代表在到达目的网络之前需要经过的下一个路由器的IP地址,即网关地址。网关是连接两个或多个网络的设备,它负责在不同网络之间转发数据包。
  Genmask是子网掩码,Use Iface是到达下一跳主机所经过的网络接口。
  在我们发送一条报文的时候路由表首先会检查是否有直接连接到目标IP地址所在网络的条目。这通常是通过子网掩码与目标IP地址进行逻辑与操作来完成的,以确定目标IP地址是否属于某个直接连接的网络。如果是,报文将直接通过相应的网络接口发送出去,而不需要经过任何路由器。
如果目标IP地址不属于直接连接的网络,路由表接下来会查找是否有更具体的路由条目(即,比默认路由更具体的路由),这些路由可能指向特定的下一跳地址或网络接口。这些特定路由通常是根据网络管理员的配置或路由协议(如RIP、OSPF等)自动学习得到的。如果路由表中没有找到直接连接或更具体的路由条目,那么最后会尝试使用默认路由(也称为默认网关)。默认路由是路由表中一个特殊的条目,它指定了当没有更具体的路由可用时,所有报文应该被发送到哪里。这通常是一个指向本地网络中的网关(路由器)的条目,该网关负责将报文转发到目标网络。

8. IP报文格式

  在上面我介绍了IP报文格式,但是遗漏了部分字段,现在我们就来认识这些被遗漏的字段:
在这里插入图片描述
  这三个字段被设计的原因其实是因为我们将要认识的下一层协议所造成的,也就是数据链路层的Mac帧协议,该协议规定一个Mac帧所能携带的有效载荷最大不能超过mtu。
  mtu,即最大传输单元(Maximum Transmission Unit)在Linux系统中可以通过ifconfig命令查到:
在这里插入图片描述
  而这个值一般也就是1500,这也意味着我们向下传输的IP报文的大小不能超过1500字节。那超过了的话怎么办?这时候就需要使用IP报文中的三个字段:16位标识、3位标志、以及13位片偏移用来对IP报文进行分片,然后将分好的数据发送到目标主机之后,再由目标主机的IP层协议进行组装
  那么我们现在就来认识这三个字段在分片与组装中的作用:

16位标识(id): 唯一的标识主机发送的报文. 如果IP报文在数据链路层被分片了, 那么每一个片里面的这个id
都是相同的.

3位标志字段: 第一位保留(保留的意思是现在不用, 但是还没想好说不定以后要用到). 第二位置为1表示禁止
分片, 这时候如果报文长度超过MTU, IP模块就会丢弃报文. 第三位表示"更多分片", 如果分片了的话,最后一
个分片置为0, 其他是1. 类似于一个结束标记.

13位分片偏移(framegament offset): 是分片相对于原始IP报文开始处的偏移. 其实就是在表示当前分片在
原报文中处在哪个位置. 实际偏移的字节数是这个值 * 8 得到的. 因此, 除了最后一个报文之外, 其他报文的
长度必须是8的整数倍(否则报文就不连续了). 

  现在我们知道了当一个IP报文长度过长时,是需要将该报文拆开,然后到了目标主机之后再被组装的。这样的机制好吗?很显然是不好的,假如每个报文丢失的概率相等,那么一个报文丢失的概率是要小于多个报文的,这么说的话,分片增加了报文丢失的概率,并且在IP协议中可没有可靠性策略,当出现组装时报文缺失的情况,IP协议会直接丢掉整个待组装的报文,而再过一段时间目标主机tcp协议没有收到报文,触发超时重传机制,这样会降低网络传输效率,并且如果传输层是udp的话,这个报文直接就丢了,所以分片机制是不好的。
  那么既然不好的话,我们就应该控制IP报文的大小,但是IP协议能控制吗?很显然也是不能的,谁能做到?那当然是被叫做传输控制协议的tcp来做啊,它可以控制报文啥时候发,发多少,出错了怎么办的一系列可靠性问题。
  所以,一个IP报文中除去20字节的报头,剩下的字段就是tcp的报头和有效载荷,而tcp的报头长度也是20字节,那么也意味着tcp报文所携带的有效载荷大小不能超过1460字节,而这个1460字节也被叫做MSS,即最大段尺寸(Max Segment Size)。一般默认情况下,大小也就是1460字节。
  而这也是我在我在介绍传输层协议tcp时,提出的一个问题:为什么tcp协议中滑动窗口中待发送的窗口有很多,这些窗口不直接一次作为一个报文发出去,而是要分开发的主要原因。

分片与组装

  在上面认识了IP协议剩下的三个字段之后,我现在就来演示一下分片与组装是如何进行的,以便加深理解:
  现在我们有一个大小为3000字节的IP报文需要发送出去,显然这个报文是需要被分片的:

分片

  那么与此同时问题就来了,这个报文需要被分几篇呢?两片吗?如果是两片的话第一片中还携带着IP报文的报头,还可以分辨16位标识以及是否分片和偏移量,但是第二片没有IP报头,那么就算发过去,也无法进行组装,因为组装是需要IP协议的报头的,所以我们这里应该分三片。
  那么现在我们就来对这个报文进行分片:
在这里插入图片描述
  这个分好的三个分片中16位标识是我随便取得,3位标志的话结尾是000,其他全是001,而片偏移,对于第一个分片来说片偏移总是0,第二个片偏移就需要计算前面报文中的数据大小,又因为片偏移的单位是8字节,所以在得到前面报文的大小之后还需要将这个大小除以8,再填入13位片偏移字段。
  关于第二个分片,它的前面只有第一个分片,第一个分片的数据大小(除去IP报头)是1480,1480 / 8 = 185,所以我们就填入185,关于第三个分片片偏移的计算也是如此(1480 + 1480) / 8 = 370。又是结尾分片所以三位标志是000。

组装

  接下来这些分片就可以被发送出去到达目标主机了,而到达目标主机之后,到达网络层之后,就要对这些分片进行组装了:
  那么在组装之前我们需要注意几个问题:

如何知道收到的报文分片了?
	可以通过3位标志来判断,如果是001,那代表分片了,如果是000但是片偏移大于0,那也代表分片了
如何保证分片收全了?
	通过片偏移等于0收到开头,通过3位标志000收到结尾,剩下的通过片偏移进行排序,然后即可检查是否收全

  在解决上面两个问题之后,组装也变得简单了,只需要对片偏移进行排序即可得到连续的完整的报文了,这时将报文向上交付即可。
  以上就是我对IP协议的理解,但是文章中还少了一部分知识,那就是NAT技术的后半部分,关于报文发出去如何回来的问题,而这个问题我会在之后的文章中再次阐述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值