网络层
网络层概述
网络层主要考虑数据传输的路上问题,在复杂的网络环境中确定一个合适的路径。
网络层设计要尽量简单,向上层只提供简单灵活的、无连接的、不保证可靠性的数据报服务。网络层不提供服务质量的承诺!
IP 数据报的格式
如何分离与封装?
两个字段:4位首部长度 16位总长度
如何向上交付(分用)?
通过8位协议来做到的,其中填充的是:上层协议是谁,那么是谁填充的呢?对于交付数据来说,那填充者是对端的传输层来填充的。
各个字段的解释
-
4位版本号:IPV4。
-
4位首部长度:和TCP报文中的4位首部长度含义相同。单位是4字节,由于IP协议规定了定长的20字节的首部,所以填充的是5,二进制就是0101。
-
8位服务类型:用来获得更好的服务。
3位优先权字段(已经弃用),4位TOS字段, 和1位保留字段(必须置为0)。4位TOS分别表示:最小延时、最大吞吐量、最高可靠性、最小成本,这四者相互冲突,只能选择一个。对于ssh/telnet这样的应用程序,最小延时比较重要;对于ftp这样的程序,最大吞吐量比较重要。 -
16位总长度:首部+数据之和,单位为字节。后文还会详细解释它。
-
16位标识:IP软件在存储器中维持了一个计数器,没产生一个数据报,计数器就加一,并将此值赋值给标识字段,但是这个“标识”并不是序号,因为IP是无连接服务,数据报不存在按序接收的问题,当数据报长度超过MTU而必须分片时,这个标识字段就被复制到所有的数据报分片的标识字段中。相同的标识字段的值,使得最后能够正确的组装成为原来的数据报。
-
3位标志字段:
第一位保留。
第二位记为DF(Don’t Fragment),意思是不能分片,DF=0时才允许分片。
第三位记为MF(More Fragment),意思是还有分片,DF=1表示后面还有分片,DF=0表示这已经是若干分片的最后一个了。 -
13位片偏移:分片相对于原始IP报文开始处的偏移量,其实就是在表示当前分片的有效载荷在原报文中是处于哪个位置。片偏移的单位是8字节,所以片偏移=起始数据/8。
-
8位生存时间:TTL,表明此数据报在网络中的寿命。随着技术的进步,后来把TTL字段的功能改为“跳数限制”。路由器在每次转发 数据报之前就把TTL值减一,若TTL减小到0,就把此数据报丢弃,不在转发。
-
8位协议:指出此数据报携带的数据是使用何种协议,以便使目的主机的IP层知道应将数据部分上交给哪个协议。
-
16位头部检验和:使用CRC进行校验,来鉴别头部是否有损坏。
-
32位源地址:发送端。
-
32位目的地址:接收端。
-
选项:我们不关心。
注意:数据报首部中“总长度”字段是指,分片后的每一个分片的首部长度+该分片的数据长度之和。
IP 报文的分片
IP分片不是大多数情况!
为什么会分片?
数据链路层一次可以往网络里发送的数据大小是有限制的 MTU:1500字节
过长的数据报要进行分片处理。
为什么要在网络层里分片?
一旦分片之后,新的报文也要添加新的报头,只有网络层对报头比较了解,数据链路层是不了解的,它也不需要关心,并不是在链路层不能分片,从技术角度也是能做的,但是一旦在链路层分片之后,数据的耦合度就提升了。
谁来组装分片?
对端的网络层IP协议来组装
如何分片?
计算过程:举一个书上的例子,简单易懂
【例4-1】一个数据报的总长度为3820字节,其数据部分为3800字节长(使用固定首部),需要分片为长度不超过1420字节的数据报片。因固定首部长度为20字节,因此每个数据报片的数据部分长度不能超过1400字节。于是分为3个数据报片,其数据部分的长度分别为1400,1400和1000字节。原始数据报首部被复制为各数据报片的首部,但必须修该有关字段的值。
请问这个分片过程传输层知道吗?
不知道,也不需要知道。
分片真的好吗?
分片是有风险的,会提高丢包的风险。所以我们一般不建议分片操作!
如果不想分片,谁说了算?
传输层!链路层规定最多接收1500字节,那么网络层最多就是1480字节,所以传输层和对端的传输层就会协商一次传输的报文字节大小,最大就向下(网络层)交付1480字节,尽量避免分片。
其中一个报文丢失了怎么办?
所以会造成组装失败,所以整个大报文全部丢弃,所以在传输层认为数据丢包了,丢包了就会由发送端重传(这是采用TCP协议的才会重传,采用UDP协议的就是真的丢包了),重复上诉过程。
总结:一般而言,我们还是要减少分片,要求TCP控制自己的单个报文大小!
IP 报文的组装
16位标识是把分片聚合在一起,13位片偏移是把分片重新排列组合在一起。
如何组装?
按照偏移量升序排序。
我怎么知道,有还是没有报文丢失了呢?
我怎么知道,报文收全了呢?
最后一个分片丢失了,是不好判定的。
这时就要用到3位标志位来判断了!
接收端是如何得知,所接受的报文是独立报文还是分片报文呢?
可以采用如下算法:
if(更多分片==1 || 片偏移>0)
{
// 分片报文
set();
}
else// (更多分片==0 && 片偏移==0)
{
// 常规报文
}
网段划分
IP地址=网络号+主机号
网络号:它标志主机或者路由器所连接的网络,保证互相连接的两个网段具有不同的表示。
主机号:它标志该主机,同一网段内,主机之间具有相同的网络号,但是必须具有不同的主机号。
- 不同的子网其实就是把网络号相同的主机放到一起。
- 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。
划分问题
通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同。那么问题来了,手动管理子网内的IP,是一个相当麻烦的事情。
- 有一种技术叫做DHCP, 能够自动的给子网内新增主机节点分配IP地址, 避免了手动管理IP的不便。
- 一般的路由器都带有DHCP功能. 因此路由器也可以看做一个DHCP服务器。
有类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
随着Internet的飞速发展,这种划分方案的局限性很快显现出来,大多数组织都申请B类网络地址,导致B类地址很快就分配完了,而A类却浪费了大量地址。
例如, 申请了一个B类地址,理论上一个子网内能允许6万5千多个主机。A类地址的子网内的主机数更多.然而实际网络架设中,不会存在一个子网内有这么多的情况. 因此大量的IP地址都被浪费掉了。
无类IP地址划分
针对浪费提出了新的划分方案,称为CIDR(Classless Interdomain Routing)。
- 引入一个额外的子网掩码(subnet mask)来区分网络号和主机号。
- 子网掩码也是一个32位的正整数. 通常用一串 "1"表示网络号,"0"表示主机号。
- 将IP地址和子网掩码进行 “按位与” 操作, 得到的结果就是网络号。
- 网络号和主机号的划分与这个IP地址是A类、B类还是C类无关。
举个划分子网的例子:
IP地址 | 140.252.20.68 | 8C FC 14 44 |
---|---|---|
子网掩码 | 255.255.255.240 | FF FF FF 00 |
网络号 | 140.252.20.64 | 8C FC 14 40 |
子网地址范围 | 140.252.20.64~140.252.20.79 |
特殊的IP
- 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网。
- 将IP地址中的主机地址全部设为1, 就成为了广播地址, 用于给同一个链路中相互连接的所有主机发送数据包。
- 127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1。
IP地址数量的限制
我们知道, IP地址(IPv4)是一个4字节32位的正整数。那么一共只有232个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地址:
Windows:
Linux上:
路由器最大的功能是可以用来组建局域网!
如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上使用任意的IP地址都可以,但是RFC 1918
规定了用于组建局域网的私有IP地址
10.*
,前8位是网络号,共16,777,216个地址。172.16.到172.31.
前12位是网络号,共1,048,576个地址。192.168.*
前16位是网络号,共65536个地址包含在这个范围中的,都成为私有IP,其余的则称为全局IP(或公网IP)。
- 一个路由器一般配置两个IP地址:一个WAN口,另一个LAN口,因为要转发报文,所以路由器要横跨两个网络。
我发起请求,在IP报文中填好目的IP和源IP,理论这样发送到了百度服务器,但是百度服务器拿到报文处理后,发现源IP,它无法识别此IP地址,因为允许局域网内私有IP地址重复。所以此时报文是无法直接发送回来的。
此时路由器的作用就出来了,帮你把你报文里的源IP地址替换成为WAN口IP,再转发给下一跳,就如同该报文是由该路由器产生的一般。
总结:我们自己的请求在对外发送的时候,我们的源IP地址可能一直在被中间路由器替换——NAT技术。
报文到达服务器后,如何回来呢?
后面再谈!
路由
基于路由,报文是如何转发的?
IP数据包的传输转发过程也和问路一样:
- 当IP数据包,到达路由器时,路由器会先查看目的IP。
- 路由器决定这个数据包是能直接发送给目标主机,还是需要发送给下一个路由器。
- 依次反复,一直到达目标IP地址。
那么如何判定当前这个数据包该发送到哪里呢? 这个就依靠每个节点内部维护一个路由表;
route命令用于查看路由表
查找过程:eg:有一个目的IP10.0.10.0,先与子网掩码按位与操作,得到的网络号与Destination对比,如果相同则就是下一跳,如此往复对比路由表,如果所有的表中都没有目的地址,那么会选择默认路由。