TCP/IP协议-网络层
文章目录
[TOC]
路由器
- 转发 当一个分组到达某路由器输入链路接口时,该路由器须将该分组移动到适当的输出链路接口的路由器本地动作。转发发生的尺度很短,因此通常用硬件来实现。它是 数据平面 唯一实现的功能。
- 路由选择 当分组从发送方流向接收方时,网络层必须决定这些分组所采用的路由和路径。计算这些路径的算法被称为路由选择算法。路由选择发生的时间尺度长,因此通常用软件来实现,它是 控制平面 实现的功能。
- 路由表 每台网络路由器内存中都有一个路由表,当收到一份数据报时,路由器检查分组首部一个或多个字段值,用于在其路由表中索引,然后进行转发分组。路由表中包含以下信息:
- 目的 IP 地址 它可以是一个完整的主机地址,也可以是一个网络地址。由该表中的标志字段指定。
- 下一跳(下一站)路由器的 IP 地址 指在一个可以直接相连网络上的路由器,可以转发的数据报。下一跳路由器不是最终目的,但它可以把传送它的数据报转发到最终目的地。
- 标志 其中一个标志指明目的
IP
地址是网络地址还是主机地址;另一个标志指明下一站路由器是否为真正的下一站路由器,还是一个直接相连的接口。 - 为数据报的传输指定一个网络接口
工作原理
当收到一份数据报进行转发时,它先要搜索路由表。当数据报来自某个网络接口时,IP
首部先检查目的IP
是否为本机IP
地址之一或者广播IP
地址。如果是,数据报被发送到由IP
首部协议字段所指定的协议模块进行处理。反之,如果IP
层被设置为路由器功能,那么就对数据报进行转发,否则数据报被丢弃。
IP
路由选择是逐跳进行的,IP
并不知道到达目的地的完整路径。所有IP
路由选择只为数据报传输提供下一站路由器的IP
地址。它假定下一站路由器比发送数据报的主机更接近目的地,且下一站路由器与该主机是直接相连的。
IP
路由选择步骤:
- 搜索路由表,寻找与目的
IP
完全匹配的表目(网络号和主机号都要匹配)。如果找到,则把报文发送给该表目指定的下一站路由器或直接连接网络接口(取决于标志字段的值)。 - 搜索路由表,寻找与目的网络号相匹配的表目。如果找到,则把报文发送给该表目指定的下一站路由器或直接网络接口(取决于标志字段的值)。网络上的所有主机可以通过这个表目进行寻径,这种搜索网络的匹配方法必须考虑可能的子网掩码。
- 搜索路由表,寻找标记为“默认(default)”的表目,如果找到,则把报文发送给该表目指定的下一站路由器。
- 如果上面步骤都没有成功,该数据报不能被发送。如果该数据报来自本机,则会向应用程序返回一个“主机或网络不可达”错误。
为网络指定一个路由器,而不必为每个主机指定一个,这是
IP
路由选择的一个基本特性。这样可以极大缩小路由表的规模,比如Internet
上路由器只有几千个表目,而不会超过100万个。
网际协议-IP
IP
是TCP/IP
协议族中最为核心的协议。所有TCP
、UDP
、ICMP
和IGMP
数据都以IP
数据报格式传输。
它不能保证IP
数据报能成功地到达目的地。 IP
仅提供最好的传输服务。如果发生某种错误时,如某个路由器暂时用完了缓冲区, IP
有一个简单的错误处理算法:丢弃该数据报,然后发送 ICMP
消息报给信源端。
它是无连接的,不维护任何数据报文的后续状态信息。每个数据报相互独立,因此IP
数据报可以不按顺序接收。当一个端向另一端发送两个数据报(A
和B
),每个数据报都是独立进行路由选择,可能选择不同线路,所以B
可能在A
之前到达。
IP首部

最高位在左边,记为0bit
; 最低位在右边,记为31bit
。
4
个字节的32bit
的值以下面次序输出:
首先,0~7bit
; 其次8~15bit
; 然后16~23bit
; 最后24~31bit
。
TCP/IP
首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序(big endian)。以其他形式存储的二进制整数的机器(如
little endian
),必须在传输数据之前把首部转换成网络字节序。
目前协议 版本(Ver) 号是4
,因此有时IP
也被称为IPv4
。
首部长度(IHL) 指的是首部占用32bit
的数目,普通IP
该字段的值为5
行(固定部分),每行 字节 ,因此首部长度为 个字节。如果有选项部分,由于首部长度为4bit
,所以最大值为 行(即取值范围 0-15),所以首部最大长度为 字节。
服务类型(TOS,Type Of Service),字段包括
-
一个
3bit
的优先权子字段(现在已被废弃),默认值000
。 -
4bit
的TOS
子字段,分别代表(最小时延、最大吞吐量、最高可靠性、最小费用),只能置其中1bit
为1
,如果均为0
,那么就意味着一般服务。
应用 | 最小延时 | 最大吞吐量 | 最高可靠性 | 最小费用 | 16进制值 |
---|---|---|---|---|---|
Telnet/Rlogin | 1 | 0 | 0 | 0 | 0x10 |
FTP | |||||
控制 | 1 | 0 | 0 | 0 | 0x10 |
数据 | 0 | 1 | 0 | 0 | 0x08 |
任意块数据 | 0 | 1 | 0 | 0 | 0x08 |
TFTP | 1 | 0 | 0 | 0 | 0x10 |
SMTP | |||||
命令阶段 | 1 | 0 | 0 | 0 | 0x10 |
数据阶段 | 0 | 1 | 0 | 0 | 0x08 |
DNS | |||||
UDP查询 | 1 | 0 | 0 | 0 | 0x10 |
TCP查询 | 0 | 0 | 0 | 0 | 0x00 |
区域查询 | 0 | 1 | 0 | 0 | 0x08 |
IMCP | |||||
差错 | 0 | 0 | 0 | 0 | 0x00 |
查询 | 0 | 0 | 0 | 0 | 0x00 |
任何IGP | 0 | 0 | 1 | 0 | 0x04 |
SNMP | 0 | 0 | 1 | 0 | 0x04 |
BOOTP | 0 | 0 | 0 | 0 | 0x00 |
NNTP | 0 | 0 | 0 | 1 | 0x02 |
1bit
的未用位(必须置0)
以
Telnet/Rlogin
应用为例,因为这两个应用主要用于传输少量交互数据,所以要求最小传输时延。其TOS
最终值为000,1000,0
,换算成十六进制为0x10
。现在大多数
TCP/IP
实现都不支持TOS
特性,但自4.3BSD Reno
以后新版本系统都对它进行了设置。另外,新路由协议OSPE
和IS-IS
都能根据这些字段进行路由决策。由于大多数实现都不使用
TOS
字段,因此像SLIP
这种排队机制自己来判断和处理,驱动程序先查看协议段(确定是否是一个TCP
段),然后检查TCP
信源和信宿的端口号,以判断是否是一个交互服务。
总长度(Total Length) 字段指整个IP
数据报长度,以字节为单位。利用首部长度和总长度字段,就可以知道IP
数据报中数据内容的起始位置和长度。由于该字段长度为16bit
,所以IP
数据报最大长度为 即,65,535字节。也就是最大传输单元(Maximum Transmission Unit,MTU) 为65,535字节。
尽管可以传输最大
65,535
字节的数据报,但大多数链路层都会对它进行分片。而且主机也要求不能接收超过576
字节的数据报。类似UDP
的应用,它们限制用户数据报长度为512
字节,小于576
字节。事实上现在大多数的实现(特别是那些支持网络的文件系统
NFS
的实现)允许超过8192
字节的IP
数据报。
标识(Identification) 字段,唯一的标识主机发送的每一分数据报。通常每发送一份报文它的值就会加1
。
RFC 791 [Postel 1981a]
认为标识字段应该由让IP
发送数据报的上层来选择。假设有两个连续的IP
数据报,其中一个是由TCP
生成的,而另一个是由UDP
生成的,那么它们可能具有相同的标识字段。尽管这也可以照常工作(由重组算法来处理),但是在大多数从伯克利派生出来的系统中,每发送一个IP
数据报,IP
层都要把一个内核变量的值加1
,不管交给IP
的数据来自哪一层。内核变量的初始值根据系统引导时的时间来设置。
TTL(time-to-live) 生存时间字段,设置了数据报可以经过的最多路由器数,指定了数据报的生存时间。初始值由源主机设置(通常为32
或64
),经过一个处理它的路由器该值减1
,当该值为0
时,数据报被丢弃,并发送ICMP
报文通知源主机。
首部检验和(Header Checksum) 字段,根据IP
首部计算的检验和码,它不对首部后面的数据进行计算。
ICMP
、IGMP
、UDP
和TCP
在它们各自的首部中均含有首部检验和码。
为了计算一份数据报的
IP
检验和,首先将检验和字段置为0
。然后,将首部中的数据按每16bit
一块分成若干块(每块包含16位的原因是检验和正好是16位,这样便于将计算结果填充到对应的16位字段),对首部中每个16bit
求和(注意当高位溢出时,需要低位回卷)后取反(即0
变成1
,1
变成0
)结果并存储到检验和字段中。第二种计算方法是,先将各字段二进制数据先取反,再求和。
抓包数据
:
Internet protocol Version 4, src: 192.168.0.109(192.168.0.109), Dst: 224.0.0.252(224.0.0.252)
Version: 4
Header length: 20bytes
Differentiated Service field: 0x00
Total length: 71
Identification: 0x1fd6 (8150)
Flags: 0x00
Fragment offset: 0
Time to live: 1
Protocol: UDP (17)
Header checksum: 0xf7be [correct]
[Good: True]
[Bad: False]
Souce: 192.168.0.109
Destination: 224.0.0.252
结合上面抓包数据,发送方检验和计算步骤见下图:

检验和求和前,首先将各字段各进制数值转换成二进制数值。如
首部长度(Header length)
数据报值为20bytes
,先将其转换成十进制值为 (行),然后再将5
转成二进制101
,由于首部长度占4bit
,所以不足位补0
,即0101
。求和时,当最高位需要进位时,进位被回卷到最低位。如上图虚线框结果,最高位,只保留数值
0
,数值1
回卷到最低位,即,其中1
就是高位回卷的数值。
接收方校验数据步骤和发送方类似,区别在于接收方不再将检验和字段置为0
,而是发送方计算好的值0xf7be
即1111011110111110
,所以接收方最终计算结果为 。如果结果每个比特位不全是1
,那么IP
将丢弃收到的数据报,但是不生成差错报文,由上层去发现丢失的数据报并进行重传。
最后一个字段是可选字段,目前这些选项定义如下:
- 安全和处理限制(用于军事领域,参见RFC 1108[Kent 1991])
- 记录路径(让每个路由器都记录下它的
IP
地址) - 时间戳(让每个路由器都记录下它的
IP
地址和时间) - 宽松源站选路(为数据指定一系列必须经过的
IP
地址) - 严格源站选路(与宽松源站选路类似,但是要求只能经过指定的
IP
地址,不能经过其他地址)
IPv4编址
一台主机通常只有一条链路连接的网络,当主机中IP
想发送一个数据报时,它就在该链路上发送。而路由器的任务是从链路上接收数据报,并从其它链路上转发出去,所以路由器必须拥有两条以上的链路。
主机、路由器与物理链路之间的边界叫作接口。IP
要求每台主机和路由器都拥有自己的IP
地址。
一个
IP
地址与一个接口关联,而不是与包括该接口的主机或路由器相关联。
子网 具有相同的前半部分地址的一组IP
地址,可以利用地址的前半部分划分组。在一个IP
网络中划分子网使我们能将一个单一的大型网络,分成若干个较小的网络。
这样做原因是A
类、B
类地址为主机分配了太多的空间,在一个网络内一般不会存在如此多主机,同时子网的存在,使得外部路由器只需要知道通往子网的IP
地址路径即可,再由子网去寻找具体子网IP
地址即可;从而不需要知道所有子网下的IP
地址路径,可以缩减路由表的规模。基于以上原因IP
允许划分更小的网络,称为子网。
大多数子网都是
B
类地址,也可以用于C
类地址,很少出现在A
类地址因为A
类地址本身就很少。但是,大多数A
类地址都是进行子网划分的。
现在所有主机都要求支持子网编址,子网编址不再把IP
地址看成单纯的的 网络号 和 主机号 组成,而是把主机号再分成一个 子网号 和 主机号 。
主机除了IP
地址外,还需要知道有多少比特留给了子网号和主机号,这个问题通过子网掩码 来解决。子网掩码也是一个32bit
的值,其中网络号
和子网号
(如果存在,不设置子网掩码情况下,即采用默认子网掩码时,子网号不存在)的值均为1
,主机号
值为0
。

如果知道本机
IP
地址,就可以知道地址分类(A、B或C类),也就知道网络号和子网号之间的分界线。而根据子网掩码可知道子网号和主机号之间的分界线。
假设主机地址:140.252.1.1(B类地址),子网掩码:255.255.255.0(8bit子网号,8bit主机号)
- 当目的地址是:140.252.4.5,可知B类网络号相同(均为140.252),子网号不同(分别为1和4)
- 当目的地址是:140.252.1.22,可知B类网络号相同(均为140.252),子网号相同(均为1),主机号不同(分别为1和22)
- 当目的地址是:192.43.235.6(C类地址),可知网络号不同,因此不需要进一步比较了
给定两个 IP 地址和子网掩码后,IP 路由选择功能一直进行这样的比较。
子网掩码
通过无类别域间路由选择(Classless Inter-Domain Routing,CIDR) 分配策略分配地址,它是一个按位,基于前缀的用于解释IP
地址的标准。当使用子网寻址时,32bit
的IP
被划分为两部分,并且也具点分有十进制数形式a.b.c.d/x
,其中x
表示地址的第一部分即最左侧开始的比特数,叫做前缀,该部分定义了子网地址。
如上例,IP地址为:140.252.1.1,子网掩码:255.255.255.0
使用 CIDR 子网掩码表示为 140.252.1.1/24
|
| 转换为二进制
V 24bit
11111111 11111111 11111111 000000000
255 255 255 0
所以子网掩码为:255.255.255.0
|
| 与 IP 按位与计算
V
11111111 11111111 11111111 000000000 子网掩码
& 10001100 11111100 00000001 000000001 IP
——————————————————————————————————————————
10001100 11111100 00000001 000000000
140 252 1 0
结果为:140.252.1.0 其表达的含义为该 IP 地址 140.252.1.1 属于 140.252.1.0 这个网络,其主机号为 1,即这个网络中编号为 1 的主机。
子网掩码一定是配合IP
地址来使用的。对于常用网络A
、B
、C
类IP
地址其默认子网掩码(缺省子网掩码即未划分子网,对应的网络号的位都置1,主机号都置0)的二进制与十进制对应关系见下表:
类型 | 子网掩码(二进制) | 子网掩码十进制: |
---|---|---|
A | 11111111 00000000 00000000 00000000 | 255.0.0.0 |
B | 11111111 11111111 00000000 00000000 | 255.255.0.0 |
C | 11111111 11111111 11111111 00000000 | 255.255.255.0 |
特殊的 IP 地址 :
网络号 | 子网号 | 主机号 | 源端 | 目的端 | 描述 |
---|---|---|---|---|---|
0 | 0 | OK | 不可能 | 网络上的主机 | |
0 | 主机号 | OK | 不可能 | 网络上的特定主机 |
ICMP
因特网控制报文协议(Internet Control Message Protocol,ICMP) ,它用于网际协议IP
中发送控制消息,提供可能发生在通信环境中的各种问题反馈。通过这些信息,使管理者可以对所发生的问题作出诊断,然后采取适当的措施解决。

ICMP
依靠IP
来完成它的任务,它是IP
的主要部分。它一般不用于在两点间传输数据。它通常不由网络程序直接使用,除了ping
和traceroute
这两个特别的程序。
报文格式

ICMP
报头从IP
报头的第160bit
开始(IP
首部按20字节,未使用可选部分计算)。
-
类型 、代码
不同类型的报文由由这两个字段共同决定,当发送一份
ICMP
差错报文时,报文始终包含IP
的首部和ICMP
差错报文的前8
个字节。这样,接收ICMP
差错报文的模块就会把它与某个特定协议和用户进程联系起来。类型 代码 描述 查询 差错 状态 0 0 回显应答(Ping应答) √ 1 和 2 - 保留 √ 未分配 3 - 目的不可达 √ ↑ 0 网络不可达 √ ↑ 1 主机不可达 √ ↑ 2 协议不可达 √ ↑ 3 端口不可达 √ ↑ 4 需要进行分片但设置了不分片比特 √ ↑ 5 源站选路失败 √ ↑ 6 目的网络不认识 √ ↑ 7 目的主机不认识 √ ↑ 8 源主机被隔离 √ 弃用 ↑ 9 目的网络被强制禁止 √ ↑ 10 目的主机被强制禁止 √ ↑ 11 对特定的TOS 网络不可达 √ ↑ 12 对特定的TOS 主机不可达 √ ↑ 13 由于过滤,通信被强制禁止 √ ↑ 14 主机越权 √ ↑ 15 优先权终止生效 √ 4 0 源端关闭(拥塞控制) √ 弃用 5 0 对网络重定向 √ ↑ 1 对主机重定向 √ ↑ 2 基于TOS 的网络重定向 √ ↑ 3 基于TOS 的主机重定向 √ 6 - 备用主机地址 √ 弃用 7 - 保留 未分配 8 0 请求回显(Ping请求) √ 9 0 路由通告 √ 10 0 路由器的发现/选择/请求 √ 11 0 TTL 超时 √ ↑ 1 分片重组超时 √ 12 0 IP 报首部参数错误(坏的I P首部) √ ↑ 1 丢失必要选项 √ ↑ 2 不支持的长度 13 0 时间戳请求 √ 14 0 时间戳应答 √ 15 0 信息请求 √ 弃用 16 0 信息应答 √ 弃用 17 0 地址掩码请求 √ 弃用 18 0 地址掩码应答 √ 弃用 -
检验和
检验和字段是必须存在的字段,覆盖整
ICMP
个报文,算法与IP
首部检验和相同。
不会产生
ICMP
差错报文的情况:
ICMP
差错报文(但是,查询ICMP
报文可能产生ICMP
差错报文)- 目的地址是广播地址或多播地址的
IP
数据报- 链路层广播的数据报
- 不是
IP
分片的第一片- 源地址不是单个主机的数据报(也就是说,源地址不能为零地址、环回地址、广播地址和多播地址)
这些规则防止过去允许
ICMP
差错报文对广播分组响应所带来的广播风暴。
ICMP 地址掩码请求与应答

ICMP
地址掩码请求用于无盘系统在引导过程中获取自己的子网掩码(这一过程与RARP
类似)。
报文中 标识符 和 序列 字段,由发送端任意指定,这些值在应答中将被返回。这样发送端就可以把应答与请求进行匹配。
ICMP 时间戳请求与应答

报文主要用于互联网机器之间同步时钟。返回的建议值是自午夜开始计算的毫秒数,协调的统一时间UTC
。这种ICMP
报文的好处是它提供了毫秒级的分辨率,而利用其他方法从别的主机获取的时间(如某些UNIX
系统提供的rdate
命令)只能提供秒级分辨率。
由于返回的时间是从午夜开始计算的,因此调用者必须通过其他方法获知当时的日期,这是它的一个缺陷。
请求端填写发起时间戳,然后发送报文。应答系统收到请求报文时填写接收时间戳,在发送应答时填写发送时间戳。但是,实际上,大多数的实现把后面两个字段都设成相同的值(提供三个字段的原因是可以让发送方分别计算发送请求的时间和发送应答的时间)。