名词解释:ICMP( Internet Control Message Protocol 网络控制消息协议 )
关键问题:为什么ICMP属于网络层
前情提要
学习计算机网络知识的时候,最开始都要死记硬背一下OSI七层或者TCP/IP五层模型的划分。
在学习网络数据封装的时候,我们也知道数据是一层包裹着一层的
但是从Linux TCP/IP协议栈实现的角度来看,我会觉得实际的设计与这个模型有一点偏差。
Linux的struct iphdr
结构体是网络层的数据包头格式,结构如下
1 | struct iphdr { |
我们可以看到IP版本、源地址目的地址等我们常见元素的定义。
其中的protocol
字段对应的是IP协议上层使用的协议,对应in.h
中的枚举定义
1 |
|
iphdr结构体头文件(ip.h) protocol定义(in.h)可以点击访问
在之前介绍ICMP数据拦截器的文章中,我们通过判断判断IP头的protocol
字段是否等于IPPROTO_ICMP
来判断数据包是否属于ICMP数据包。
换句话来说,ICMP协议是由IP协议所承载,运行在IP协议之上,而TCP和UDP协议也是运行在IP协议之上。
但是,在五层模型中,ICMP协议属于网络层的协议,而TCP/UDP属于传输层。
如果对于TCP类型的数据来说,数据封装会类似这样
【以太网帧头【IP报文【TCP头【data 】 】 】 】
也就是 物理/数据链路层帧头 + 网络层报文 + 传输层报文 + 上层应用数据组成
对于ICMP类型的数据来说,封装是这样的
【以太网帧头【IP报文【ICMP头【data 】 】 】 】
所以就是 物理/数据链路层帧头 + 网络层报文 + 网络层报文 + data ?
为什么ICMP属于网络层
在网上搜索了一下,我觉得在知乎上看到作者车小胖的解释比较能帮助我的理解 ,点击访问知乎原文
简单来说,应用层的HTTP协议、网络层的TCP协议,都有自己的纠错机制,当数据不可达时,可以有抛出错误的办法。
但是IP协议包头部分并没有相关的错误通知机制,假设只有IP协议的情况,如果客户端发送了一个请求到服务器,但是服务器内核协议栈解析发现服务器上并没有对应的端口在监听,那么客户端可能就只能知道发出的数据没有响应,但并不清楚是由于网络传输过程中的原因导致,还是服务器的原因导致。
而在有ICMP协议的情况下,如果服务端没有监听对应的端口,客户端发送数据过来时,内核协议栈会返回一个ICMP报文,由ICMP表明当前目的不可达(ICMP_DEST_UNREACH),不可达的具体的原因是端口不可达(ICMP_PORT_UNREACH)。
因此,ICMP可以被认为是IP协议的附属协议,ICMP协议基于IP协议,为网络的连通性提供指示。
如何理解网络层与传输层的划分
经过了第二部分的解释,我们应该可以理解为什么ICMP与TCP都基于IP协议,但ICMP属于网络层的原因。
我们来列举一下场景的网络层协议和传输层协议(TCP/IP五层模型)
网络层:
- IP
- ICMP
- IGMP
- ARP(OSI七层模型中属于数据链路层)
- VRRP
传输层:
- TCP
- UDP
融会贯通一下,我这样来理解网络层和传输层
- 网络层:组建网络或者指示网络运行情况,提供路由选择等功能
- 传输层:基于网络层,负责为应用层提供传输数据的能力,并屏蔽IP类型/物理网络接口类型等信息
你们觉得这样理解对吗? 这样是否能更容易理解TCP/IP五层模型了呢?