汇总
汇总
参考
知乎@捡田螺的小男孩
知乎@Linux
网络
对于同一台设备上的进程通信,有很多方式比如管道、消息队列、共享内存等,而对于不同设备上的进程通信,就需要网络通信,而设备是多样的,为了兼容多样的设备,协商一套通用的网络协议。


OSI 七层模型
是国际标准化组织提出一个网络分层模型,其大体结构以及每一层提供的功能如下图所示:

可以将 TCP / IP 模型看作是 OSI 七层模型的精简版本,由以下 4 层组成:
- 应用层
- 传输层
- 网络层
- 网络接口层(链路层)

应用层
专注提供功能,而不去关心数据如何传输;
工作在操作系统的用户态,而传输层及以下是内核态
应用层位于传输层之上,主要提供两个终端设备上的应用程序之间信息交换的服务,它定义了信息交换的格式,消息会交给下一层传输层来传输。 我们把应用层交互的数据单元称为报文。
协议有:HTTP协议,SMTP协议、FTP、SSH、IMAP、DNS、DHCP。
HTTP:基于TCP,1.1 默认长连接,无状态,通过Session记录状态。
SMTP:基于TCP,用来发送电子邮件。(接收邮件不是SMTP,而是POP3/IMAP)。
FTP:基于TCP,提供文件传输服务,好处是屏蔽操作系统和文件存储方式。
FTP 是基于客户—服务器(C/S)模型而设计的,在客户端与 FTP 服务器之间建立两个连接。如果我们要基于 FTP 协议开发一个文件传输的软件的话,首先需要搞清楚 FTP 的原理。关于 FTP 的原理,很多书籍上已经描述的非常详细了:
FTP 的独特的优势同时也是与其它客户服务器程序最大的不同点就在于它在两台通信的主机之间使用了两条 TCP 连接(其它客户服务器应用程序一般只有一条 TCP 连接):
- 控制连接:用于传送控制信息(命令和响应)
- 数据连接:用于数据传送;
这种将命令和数据分开传送的思想大大提高了 FTP 的效率。

传输层
为应用层提供网络支持
传输层报文携带端口,以此来区分不同应用
端到端的,将报文收发于应用之间
传输层的主要任务就是负责向两台终端设备进程之间的通信提供通用的数据传输服务。
主要使用以下两种协议:
- 传输控制协议 TCP(Transmisson Control Protocol)--提供面向连接的,可靠的数据传输服务。(三次握手,四次挥手)
- 用户数据协议 UDP(User Datagram Protocol)--提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。
如何实现一个可靠的UDP?※ #question
| TCP | UDP | |
|---|---|---|
| 连接性 | 面向连接 | 面向非连接 |
| 传输可靠性 | 可靠 | 不可靠 |
| 报文 | 面向字节流 | 面向报文 |
| 效率 | 传输效率低 | 传输效率高 |
| 流量控制 | 滑动窗口 | 无 |
| 所需资源 | 多 | 少 |
| 拥塞控制 | 慢开始、拥塞避免、快重传、快恢复 | 无 |
| 传输速度 | 慢 | 快 |
| 应用场合 | 对效率要求低,对准确性要求高或要求有连接的场景(文件传输,邮件收发) | 对效率要求高,对准确性要求低(即时通信) |
网络层
点对点,将报文传输于设备之间
网络层负责为分组交换网上的不同主机提供通信服务。
网络层最常使用的就是 IP 协议,而不同的主机之间通过 IP 地址来进行区分。
在发送数据时,网络层把传输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报,简称数据报。
互联网是由大量的异构(heterogeneous)网络通过路由器(router)相互连接起来的。互联网使用的网络层协议是无连接的网际协议(Internet Protocol)和许多路由选择协议,因此互联网的网络层也叫做网际层或IP 层。

网络接口层
为什么有MAC地址?※ #question
我们可以把网络接口层看作是数据链路层和物理层的合体。
- 数据链路层(data link layer)通常简称为链路层( 两台主机之间的数据传输,总是在一段一段的链路上传送的)。数据链路层的作用是将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。
- 物理层的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异

网络为什么要分层?
- 各层之间相互独立:各层之间不需要关心其他层是如何实现的,只需要知道自己如何调用下层提供好的功能就可以了(可以简单理解为接口调用)。
- 提高了整体灵活性 :每一层都可以使用最适合的技术来实现,你只需要保证你提供的功能以及暴露的接口的规则没有改变就行了。这个和我们平时开发系统的时候要求的高内聚、低耦合的原则也是可以对应上的。
- 大问题化小 : 分层可以将复杂的网络间题分解为许多比较小的、界线比较清晰简单的小问题来处理和解决。这样使得复杂的计算机网络系统变得易于设计,实现和标准化。 这个和我们平时开发的时候,一般会将系统功能分解,然后将复杂的问题分解为容易理解的更小的问题是相对应的,这些较小的问题具有更好的边界(目标和接口)定义。
不同层之间的报文变化


HTTP协议
基本概念
HTTP 协议,全称超文本传输协议(Hypertext Transfer Protocol)。顾名思义,HTTP 协议就是用来作为超文本(超文本,文字图片视频超链接),在浏览器和服务器端的传输的约定和规范。
并且,HTTP 是一个无状态(stateless)协议,也就是说服务器不维护任何有关客户端过去所发请求的消息。
HTTP是应用层协议,以TCP作为底层协议。
HTTP常见状态码

1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。
- 「200 OK」是最常见的成功状态码,表示一切正常。如果是非
HEAD请求,服务器返回的响应头都会有 body 数据。 - 「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
- 「206 Partial Content」是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。
3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
- 「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。
- 「302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
- 「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。
4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
- 「400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。
- 「403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。
- 「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
- 「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
- 「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
HTTP常见字段
#question
通用字段
| 字段名 | 字段作用 |
|---|---|
| Content-Type | 数据类型 |
| Content-Length | 数据长度 |
请求字段
| 字段名 | 字段作用 |
|---|---|
| Accept | 客户端可以接受哪种格式的数据 |
| Accept-Encoding | 可接受的编码 |
| Host | 指定服务器的域名 |
| Connection | 客户端要求服务器使用TCP持久连接(keep-alive),以便复用 |
响应字段
| 字段名 | 字段作用 |
|---|---|
| content-encoding | 数据压缩格式 |
HTTP头部分为四种:通用标头、实体标头、请求标头、响应标头。
通用标头
实体标头
请求标头
响应标头
HTTP请求方式

其中,POST、DELETE、PUT、GET 的含义分别对应我们最熟悉的增、删、改、查。
Get、Post的区别
| 比较项 | Get | Post |
|---|---|---|
| 语义 | 获取资源 | 创建或修改资源 |
| 安全幂等 | 是 | 否 |
| 缓存 | 可以缓存 | 不会被缓存 |
| 数据量 | 小(URL有长度限制,但本身并没规定) | body无限制 |
| 快慢 | 快 | 慢 |
注:这里的安全是指不会对服务器的资源造成破坏
#question Get比Post快的原因
HTTP缓存技术
强制缓存
通过HTTP响应头字段—— Cache-Control, Expires 来实现。
都用来表示资源在客户端的有效期:
Cache-Control:相对时间
Expires:绝对时间
前者优先级高。
过程:
- 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
- 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
- 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。
协商缓存
通过请求头字段,两种实现:If-Modified-Since,If-None-Match
If-Modified-Since
与响应头中的 Last-Modified 字段结合使用。
过程
- 响应头部中的
Last-Modified:标示这个响应资源的最后修改时间; - 请求头部中的
If-Modified-Since:当资源过期了,发现响应头中具有 Last-Modified 声明,则再次发起请求的时候带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since 则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。
If-None-Match
与响应头字段 Etag 结合使用。
注意:只有没有命中强制缓存的时候才能带有协商缓存字段请求

HTTP 协议通信过程
HTTP 是应用层协议,它以 TCP(传输层)作为底层协议,默认端口为 80. 通信过程主要如下:
- 服务器在 80 端口等待客户的请求。
- 浏览器发起到服务器的 TCP 连接(创建套接字 Socket)。
- 服务器接收来自浏览器的 TCP 连接。
- 浏览器(HTTP 客户端)与 Web 服务器(HTTP 服务器)交换 HTTP 消息。
- 关闭 TCP 连接。
HTTP1.1特点
长连接
请求应答不必马上关闭,可以重用,减少了通讯开销。
管道传输
长连接使得管道传输成为可能,多个请求不必等待其他请求回来就可以发送,减少整体响应时间,(服务器必须接受请求的顺序进行响应)
解决了请求的队首阻塞,并没有解决响应的队首阻塞。
相比于HTTPS存在哪些风险?
- 窃听风险:信息泄露,机密性
- 篡改风险:信息非原始,完整性
- 冒充风险:假信息,真实性
HTTPS协议
混合加密、摘要算法+数字签名、数字证书
基本概念
HTTPS 协议(Hyper Text Transfer Protocol Secure),是 HTTP 的加强安全版本。HTTPS 是基于 HTTP 的,也是用 TCP 作为底层协议,并额外使用 SSL/TLS 协议用作加密和安全认证。默认端口号是 443。
优点
保密性好,信任度高。
混合加密
非对称加密 ※
SSL/TLS 的核心要素是非对称加密。非对称加密采用两个密钥——一个公钥,一个私钥。在通信时,私钥仅由解密者保存,公钥由任何一个想与解密者通信的发送者(加密者)所知。
对称加密 ※
摘要算法和数字签名
发送端发送 内容和哈希值,接收端通过相同的摘要算法,对接受内容进行加密,比对接收到的和生成的哈希值,如果不同说明内容被篡改。(但这并不能判断是否被替换)
对哈希值进行私钥加密作为数字签名,接收端将数字签名通过公钥解密,比对解密后哈希和计算出来的哈希,可以判断是否修改(可解决替换)。
数字证书
#question CA如何验证数字证书

- 身份验证部分与数字签名的原理相似
客户端验证
- 客户端判断当前证书是否是根证书,如果不是则向上请求证书颁发者,直到找到根证书。
- 根证书,通过身份验证(自验证)
- 向下信任。
建立连接过程
SSL/TLS 协议基本流程
- 客户端向服务器索要并验证服务器的公钥
- 双方协商会话密钥
- 双方以会话密钥加密通信
前两步是 TLS 的建立过程。
TLS 1.2四次握手
TLS 1.3三次握手

HTTPS如何保证完整性
TLS分为握手协议和记录协议。
记录协议主要负责消息(HTTP数据)的压缩,加密以及数据的认证。
- 首先,消息被分割成多个较短的片段,然后分别对每个片段进行压缩。
- 接下来,经过压缩的片段会被加上消息认证码(MAC 值,这个是通过哈希算法生成的),这是为了保证完整性,并进行数据的认证。通过附加消息认证码的 MAC 值,可以识别出篡改。与此同时,为了防止重放攻击,在计算消息认证码时,还加上了片段的编码。
- 再接下来,经过压缩的片段再加上消息认证码会一起通过对称密码进行加密。
- 最后,上述经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。
HTTP系列协议版本比较
HTTP/1.0与HTTP/1.1
状态响应码:1.0仅定义了16种状态码,1.1新增了许多。
缓存处理 ※
HTTP1.1 在1.0的基础上大大增加了灵活性和扩展性。
Last-Modified标签,标记被请求资源最后一次修改。
客户端,再次请求If-Modified-Since标签,询问此时间之前是否被修改。
服务器判断,如果已修改,返回 200 OK的响应体+资源;反之,返回304 not modified。

连接方式
长连接
进行一次数据传输后,不关闭连接,长期保持连通状态。如果两个应用程序之间有新的数据需要传输,则直接复用这个连接,无需再建立一个新的连接。
优点
在多次通信中可以省去连接建立和关闭连接的开销,并且从总体上来看,进行多次数据传输的总耗时更少。缺点是需要花费额外的精力来保持这个连接一直是可用的
短连接
短连接意味着每一次的数据传输都需要建立一个新的连接,用完再马上关闭它。下次再用的时候重新建立一个新的连接,如此反复。
优缺点
它的优势是由于每次使用的连接都是新建的,所以基本上只要能够建立连接,数据就大概率能送达到对方。并且哪怕这次传输出现异常也不用担心影响后续新的数据传输,因为届时又是一个新的连接。缺点是每个连接都需要经过三次握手和四次握手的过程,耗时大大增加。
http
1.0:默认短连接。每进行一次HTTP操作就建立一次连接欸,任务结束就中断连接。缺点:导致大量的握手报文和挥手报文占用带宽。
1.1:默认长连接模式,连接建立后不关闭(超时断开)
但两者都有长连接和短连接的方式。HTTP/1.0仍提供了长连接选项,即在请求头中加入Connection: Keep-alive。同样的,在HTTP/1.1中,如果不希望使用长连接选项,也可以在请求头中加入Connection: close。
Host头处理
DNS允许多个主机名绑定到同一个ip地址。
1.0 未考虑;1.1在请求头种添加了主机名
假设我们有一个资源URL是http://example1.org/home.html,HTTP/1.0的请求报文中,将会请求的是GET /home.html HTTP/1.0,也就是不会加入主机名。HTTP/1.1在请求头中加入了Host字段。加入Host字段的报文头部将会是:
GET /home.html HTTP/1.1
Host: example1.org
带宽优化 ※
总
| HTTP1.0 | HTTP1.1 | |
|---|---|---|
| 响应状态码 | 16种 | 加入大量 |
| 缓存处理 | 请求头If-Modified-Since | 请求头Cache-Control |
| 连接方式 | 默认短连接(提供长连接,需要请求头Connection: Keep-alive) | 默认长连接(不使用可以请求头中加入Connection: close) |
| HTTP | HTTPS | |
|---|---|---|
| 端口 | 80 | 443 |
| 报文 | 明文 | 报文加密 |
| 安全性 | 低 | 高 |
| 响应速度 | 快 | 慢 |
| 连接建立 | TCP三次握手 | TCP三次握手,SSL/TLS三次握手 |
| HTTP/1.0 | HTTP/1.1 | HTTP/2 | HTTP3 | |
|---|---|---|---|---|
| 连接方式 | 短连接 | 长连接(减少性能开销) | ||
| 管道传输(解决队首 | ||||
HTTP/1
改进:
- 长连接:减少了频繁关闭连接的性能开销
- 管道传输:解决请求的队首阻塞问题
仍不足:
HTTP/2
改进
- 基于HTTPS,安全性有保障
- 头部压缩:同时发送多个请求,如果请求头相似或一样,协议帮助消除重复部分。
- 二进制格式:报文采用二进制格式,头信息和数据体都是二进制,接收到报文不必将明文转化为二进制,可以直接解析,提高数据传输速率。 #question 如何解析
- 数据流 #question 是否解决了响应队首阻塞问题
- 多路复用:一个连接中并发多个请求或响应(请求响应都有),解决响应队首阻塞问题,降低了延迟,大大提高了连接的利用率 #question 与数据流有什么联系
仍不足
- 虽然解决了 HTTP 层的请求响应的队首阻塞问题,但 TCP 层的队首阻塞问题仍存在(前一个收到 TCP 数据未收到前,后面的要等到收到才能发送给应用,否则只能存放于缓冲区)
HTTP/3
改进
- 将 TCP 协议改为了基于 UDP 的 QUIC 协议。 #question QUIC协议
SMTP
TCP
两张动图-彻底明白TCP的三次握手与四次挥手_qzcsu的博客-CSDN博客_三次握手四次挥手详解
23-tcp协议——TIME_WAIT状态和FIN_WAIT2状态 - LiuYanYGZ - 博客园 (cnblogs.com)
基本概念
TCP 是面向连接的、可靠的、基于字节流的传输层协议。
如何唯一确定一个 TCP 连接?
源地址、源端口、目标地址、目标端口。(端口-TCP,地址-IP)
最大 TCP 连接数 = 客户端 IP 数 * 客户端端口数
报文首部格式
看一下 TCP 报文首部的格式:

- 16 位端口号:源端口号,主机该报文段是来自哪里;目标端口号,要传给哪个上层协议或应用程序
- 32 位序号:一次 TCP 通信(从 TCP 连接建立到断开)过程中某一个传输方向上的字节流的每个字节的编号(解决乱序问题)。
- 32 位确认号:用作对另一方发送的 tcp 报文段的响应。其值是收到的 TCP 报文段的序号值加 1。
- 4 位首部长度:表示 tcp 头部有多少个 32bit 字(4 字节)。因为 4 位最大能标识 15,所以 TCP 头部最长是 60 字节。
- 6 位标志位:URG(紧急指针是否有效),ACk(表示确认号是否有效),PST(缓冲区尚未填满),RST(表示要求对方重新建立连接,强制断开),SYN(建立连接消息标志接),FIN(表示告知对方不会再有数据发送,本端要关闭连接了)
- 16 位窗口大小:是 TCP 流量控制的一个手段。这里说的窗口,指的是接收通告窗口。它告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
- 16 位校验和:由发送端填充,接收端对 TCP 报文段执行 CRC 算法以检验 TCP 报文段在传输过程中是否损坏。注意,这个校验不仅包括 TCP 头部,也包括数据部分。这也是 TCP 可靠传输的一个重要保障。
- 16 位紧急指针:一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP 的紧急指针是发送端向接收端发送紧急数据的方法。
MSS
MTU: 一个数据包的最大长度
MSS: 除去 IP 和 TCP 头部之后,一个网络包能容纳的 TCP 数据的最大长度.
#question MSS
TCP 连接
连接队列
SYN(半连接)队列
Accept(全连接)队列
三次握手

如下图所示,下面的两个机器人通过 3 次握手确定了对方能正确接收和发送消息(图片来源:《图解 HTTP》)。

所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。

第一次握手(SYN=1, seq=x)
建立连接。客户端发送连接请求报文段,这是报文首部中的同步位SYN=1,同时选择一个初始序列号 seq=x ,此时,客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号;
第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1)
服务器收到客户端的SYN报文段,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号ACKnum=x+1,同时,自己还要发送SYN请求信息,SYN=1,为自己初始化一个序列号 seq=y,服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号
第三次握手(ACK=1,ACKnum=y+1)
客户端收到服务器的SYN+ACK报文段,再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,确认号 ACKnum = y+1,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED(已建立连接)状态,完成TCP三次握手。
注意:前两次握手不能携带数据,第三次握手可以
查看 TCP 状态:netstat -napt
为什么 需要三次握手/不是两次、四次 呢?
三个原因:
- 三次握手才能阻止历史重复连接的初始化
- 三次握手才能同步双方的序列号
- 三次握手才能避免资源浪费
原因1:阻止历史重复连接的初始化
当客户端发多次 SYN 建立连接的报文,在网络拥堵的环境下:
- 旧的 SYN 报文 先于 新的 SYN 报文到达服务端
- 服务端 返回 SYN + ACK 给客户端
- 客户端接收到后,根据序列号过期或超时判断是历史连接,客户端发送 RST 报文给服务端,终止这个旧的连接请求。
如果是两次握手,那么就不会有第三步判断历史连接的过程。
原因2:同步双方的序列号
TCP 协议的通信双方,必须维护一个序列号,是可靠传输的关键因素,作用如下:
- 接收方可以去除重复的数据
- 接收方可以根据数据包的序列号接收
- 表示发出去的数据包哪些被对方收到
连接建立的条件:
建立连接时,双方需要知晓对方的序列号才行。
在建立连接时,一个 SYN 报文回复一个 ACK 报文。
基于上述两个条件,是需要四次握手的(①A SYN②B ACK③B SYN④A ACK)。不过,二三步可以合并优化,确认序列号的同时发送自己的序列号,所以就成为了 三次握手。
而两次握手是只能保证一方的序列号成功接收,无法保证双端的。
原因3:避免资源浪费
实际是原因1的结果,如果是两次握手,会造成过期失效的连接请求成功建立并分配资源(实际并没有数据在当前连接传输),造成资源浪费。
每次建立连接,初始化序列号为什么要求不一样?
- 防止历史报文被下一个相同四元组的连接接收
- 为了安全性,防止黑客伪造相同序列号的 TCP 报文被对方接受
三次握手每一次没有收到报文会发生?
【转】面试必备:计算机网络常问的六十二个问题(建议收藏) - 知乎 (zhihu.com)
第一次握手丢失
请求方发送 SYN 后迟迟接收不到 ACK, 会触发超时重传机制, 重传 SYN 报文.
第二次握手丢失
接受方接收到 SYN 后, 发送 SYN-ACK, 丢失第二次握手, 触发超时重传机制, 重传 SYN-ACK
第三次握手丢失
接受方发送到 SYN-ACK 后, 丢失第三次握手, 触发超时重传机制, 重传 SYN-ACK
SYN 攻击
四次挥手
TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作。

第一次挥手(FIN=1,seq=x)
主机1(可以使客户端,也可以是服务器端),设置seq=x,向主机2发送一个FIN报文段;此时,主机1进入
FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;第二次挥手(ACK=1,ACKnum=x+1)
主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknum=x+1,主机1进入
FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;第三次挥手(FIN=1,seq=y)
主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入
LAST_ACK状态第四次挥手(ACK=1,ACKnum=y+1)
主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入
TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了,进入CLOSED状态。主机 1 等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入
CLOSED状态。
为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
由于 TCP 协议是全双工的,也就是说客户端和服务端都可以发起断开连接。两边各发起一次断开连接的申请,加上各自的两次确认,看起来就像执行了四次挥手。
#question 调用 close 函数发送 FIN 报文?
四次挥手每次丢失发生什么?
第一次挥手丢失
请求方接收不到 ACK ,触发超时重传 重发 FIN 报文,重发次数
tcp_orphan_retries控制,超出不在发送 FIN 报文,而是直接进入 CLOSE 状态第二次挥手丢失 #question
由于处于 FIN_WAIT_2 状态, 无法发送和接收数据,持续时间不会太久,超过
tcp_fin_timeout(60)会直接关闭。(shutdown 不受影响)第三次
重发 FIN ,同第一次挥手
第四次
TIME_WAIT状态,重发 ACK ,更新时间。
为什么 TIME_WAIT 状态需要经过2MSL?
(最大报文段生存时间)
虽然按道理,四个报文都发送完毕,我们可以直接进入 CLOSE 状态了,但是我们必须假象网络是不可靠的,有可以最后一个 ACK 丢失。所以 TIME_WAIT 状态就是用来重发可能丢失的ACK报文。
还有一个原因,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个 2MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
为什么需要 TIME_WAIT 状态?
主动发起关闭方才会有 TIME_WAIT 状态
- 防⽌旧连接的数据包。如果客户端收到服务端的 FIN 报文之后立即关闭连接,但是此时服务端对应的端口并没有关闭,如果客户端在相同端口建立新的连接,可能会导致新连接收到旧连接残留的数据包,导致不可预料的异常发生。
- 保证连接正确关闭。假设客户端最后一次发送的 ACK 包在传输的时候丢失了,由于 TCP 协议的超时重传机制,服务端将重发 FIN 报文,如果客户端没有维持 TIME-WAIT 状态而直接关闭的话,当收到服务端重新发送的 FIN 包时,客户端就会使用 RST 包来响应服务端,导致服务端以为有错误发生,然而实际关闭连接过程是正常的。
TIME_WAIT 状态过多危害?
- 占用系统资源,比如文件描述符,内存资源,CPU 资源等
- 占用端口资源
对于客户端 TIME_WAIT 过多,占满端口资源,会无法对目标 IP + Port 发起连接。
对于服务器 TIME_WAIT 过多,由于只监听 一个端口,通过源 IP + Port,建立多个连接,但会占用系统资源。
#question TIME_WAIT 优化
建立连接,客户端故障会怎样?
保活机制
定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。
TCP如何保证传输可靠
可靠传输的最终目的是保证数据接收的不重不漏有序,在这基础上进行优化

对于可靠性,TCP通过以下方式进行保证:
- 连接管理:三次握手,四次挥手保证建立连接和释放连接的可靠性。
- 数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时TCP发送数据端超时后会重发数据;
- 对失序数据包重排序:既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对失序数据进行重新排序,然后才交给应用层;
- 丢弃重复数据:对于重复数据,能够丢弃重复数据;
- 应答机制:当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
- 超时重发:当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
- 流量控制:TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。TCP使用的流量控制协议是可变大小的滑动窗口协议。
- 拥塞控制: 当网络拥塞时,减少数据的发送。(采用慢启动机制)
ARQ 协议 ※
自动重传请求(Automatic Repeat-reQuest,ARQ)是 OSI 模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议。
停止等待 ARQ 协议
停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认(回复 ACK)。如果过了一段时间(超时时间后),还是没有收到 ACK 确认,说明没有发送成功,需要重新发送,直到收到确认后再发下一个分组。
在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认。
优缺点:
- 优点: 简单
- 缺点: 信道利用率低,等待时间长
1) 无差错情况:
发送方发送分组, 接收方在规定时间内收到, 并且回复确认. 发送方再次发送。
2) 出现差错情况(超时重传):
停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重传时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为 自动重传请求 ARQ 。另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。连续 ARQ 协议 可提高信道利用率。发送维持一个发送窗口,凡位于发送窗口内的分组可连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组位置的所有分组都已经正确收到了。
3) 确认丢失和确认迟到
- 确认丢失 :确认消息在传输过程丢失。当 A 发送 M1 消息,B 收到后,B 向 A 发送了一个 M1 确认消息,但却在传输过程中丢失。而 A 并不知道,在超时计时过后,A 重传 M1 消息,B 再次收到该消息后采取以下两点措施:1. 丢弃这个重复的 M1 消息,不向上层交付。 2. 向 A 发送确认消息。(不会认为已经发送过了,就不再发送。A 能重传,就证明 B 的确认消息丢失)。
- 确认迟到 :确认消息在传输过程中迟到。A 发送 M1 消息,B 收到并发送确认。在超时时间内没有收到确认消息,A 重传 M1 消息,B 仍然收到并继续发送确认消息(B 收到了 2 份 M1)。此时 A 收到了 B 第二次发送的确认消息。接着发送其他数据。过了一会,A 收到了 B 第一次发送的对 M1 的确认消息(A 也收到了 2 份确认消息)。处理如下:1. A 收到重复的确认后,直接丢弃。2. B 收到重复的 M1 后,也直接丢弃重复的 M1。
连续 ARQ 协议
连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。
优缺点:
- 优点: 信道利用率高,容易实现,即使确认丢失,也不必重传。
- 缺点: 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5 条 消息,中间第三条丢失(3 号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。
重传机制
- 超时重传
- 快速重传
超时重传
发生超时重传的情况:
- 数据包丢失
- 确认应答丢失
归根到底,就是没有收到 ACK 时,就会重传。
RTT(往返时延)

RTO (超时重传时间)

超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。
#question RTO 计算
快速重传
非时间驱动,而是数据驱动重传。

三次接收到同样的 ACK 触发重传机制。
有两种选择:重传 当前 ACK、重传当前ACK(含之后)
SACK 方法
D-SACK 方法
滑动窗口
4.2 TCP 重传、滑动窗口、流量控制、拥塞控制 | 小林coding (xiaolincoding.com)
一篇带你读懂TCP之“滑动窗口”协议 - 掘金 (juejin.cn)
解析TCP之滑动窗口(动画演示)_SilentAssassin的博客-CSDN博客_tcp滑动窗口
动画演示 ※
窗口大小:无需等待确认应答,就可以发送数据的最大值。
窗口的大小由什么决定
TCP 头有一个字段 window,就是窗口大小,接收端通过这个字段告诉发送端自己还有多少缓冲区可以接收数据,发送端根据这来发送数据。
TCP每发送一个数据就进行一次确认应答,当上一个数据包收到应答再发送下一个。
这会造成报的往返时间长,网络吞吐量低,通信效率低。
发送方的滑动窗口
我们先来看看发送方的窗口,下图就是发送方缓存的数据,根据处理的情况分成四个部分,其中深蓝色方框是发送窗口,紫色方框是可用窗口:

- #1 是已发送并收到 ACK确认的数据:1~31 字节
- #2 是已发送但未收到 ACK确认的数据:32~45 字节
- #3 是未发送但总大小在接收方处理范围内(接收方还有空间):46~51字节
- #4 是未发送但总大小超过接收方处理范围(接收方没有空间):52字节以后
程序是如何表示发送方的四个部分的呢?
TCP 滑动窗口方案使用三个指针来跟踪在四个传输类别中的每一个类别中的字节。其中两个指针是绝对指针(指特定的序列号),一个是相对指针(需要做偏移)。

SND.WND:表示发送窗口的大小(大小是由接收方指定的);SND.UNA:是一个绝对指针,它指向的是已发送但未收到确认的第一个字节的序列号,也就是 #2 的第一个字节。SND.NXT:也是一个绝对指针,它指向未发送但可发送范围的第一个字节的序列号,也就是 #3 的第一个字节。- 指向 #4 的第一个字节是个相对指针,它需要
SND.UNA指针加上SND.WND大小的偏移量,就可以指向 #4 的第一个字节了。
那么可用窗口大小的计算就可以是:
可用窗口大小 = SND.WND -(SND.NXT - SND.UNA)
接收方的滑动窗口
接下来我们看看接收方的窗口,接收窗口相对简单一些,根据处理的情况划分成三个部分:
- #1 + #2 是已成功接收并确认的数据(等待应用进程读取);
- #3 是未收到数据但可以接收的数据;
- #4 未收到数据并不可以接收的数据;

其中三个接收部分,使用两个指针进行划分:
RCV.WND:表示接收窗口的大小,它会通告给发送方。RCV.NXT:是一个指针,它指向期望从发送方发送来的下一个数据字节的序列号,也就是 #3 的第一个字节。- 指向 #4 的第一个字节是个相对指针,它需要
RCV.NXT指针加上RCV.WND大小的偏移量,就可以指向 #4 的第一个字节了。
TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。

从上面的图可以看到滑动窗口左边的是已发送并且被确认的分组,滑动窗口右边是还没有轮到的分组。滑动窗口里面也分为两块,一块是已经发送但是未被确认的分组,另一块是窗口内等待发送的分组。随着已发送的分组不断被确认,窗口内等待发送的分组也会不断被发送。整个窗口就会往右移动,让还没轮到的分组进入窗口内。
可以看到滑动窗口起到了一个限流的作用,也就是说当前滑动窗口的大小决定了当前 TCP 发送包的速率,而滑动窗口的大小取决于拥塞控制窗口和流量控制窗口的两者间的最小值。
流量控制
接收方的接收缓存是有限的,当不能及时读取收到的数据而发送方仍持续发送时,会导致缓存溢出,为了解决这个问题,引入流量控制。通过向发送方发送流量窗口大小,让发送方调整滑动窗口大小来调整数据流量。
当发送窗口大小为0时,发送方不在发送数据。
窗口关闭,互为等待?
TCP 为每个连接设有一个持续的定时器,只要 TCP 连接一方接收到 对方的零窗口通知,就启动;如果超时,发送窗口探测报文,获取最新可用的窗口大小。
拥塞控制
不是有流量控制了么?要拥塞控制干什么?
流量控制是为了处理端到端速率不匹配问题,通过调整发送端发送速率来保证接收端能够及时平滑的接收数据;拥塞控制是为了解决端与系统之间的速率问题,发送端根据系统网络拥塞程度调整拥塞窗口大小,避免进一步拥塞。
什么是拥塞窗口?和发送窗口有什么关系呢?
拥塞窗口 cwnd是发送方维护的一个的状态变量,它会根据网络的拥塞程度动态变化的。前面提到过发送窗口 swnd 和接收窗口 rwnd 是约等于的关系,那么由于加入了拥塞窗口的概念后,此时发送窗口的值是swnd = min(cwnd, rwnd),也就是拥塞窗口和接收窗口中的最小值。
那么怎么知道当前网络是否出现了拥塞呢?
当发送方没有在规定时间内接收到ACK应答报文(发送的数据丢失),也就是发生了超时重传,就会认为发送了拥塞。
TCP拥塞控制的四种算法:慢开始、拥塞避免、拥塞发生、快恢复。
慢开始
所谓慢启动就是TCP 在刚建立连接完成后,一点一点的提高发送数据包的数量。
规则:当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1。
如下图,一开始cwnd=1,ack=1 →cwnd=2,ack=2 →cwnd=4,ack=4 → ....

cwnd上涨到什么程度?
有一个叫慢启动门限 ssthresh (slow start threshold)状态变量。
- 当
cwnd<ssthresh时,使用慢启动算法。 - 当
cwnd>=ssthresh时,就会使用「拥塞避免算法」。
拥塞避免
作用如其名,此时还未发生阻塞,但接下来可能发生阻塞,所以降低cwnd的增长速度,避免拥塞。
一般来说 ssthresh 的大小是 65535 字节。
规则:每当收到一个 ACK 时,cwnd 增加 1/cwnd。
如下图,拥塞避免开始cwnd=8,ack=8 →cwnd=9,ack=9 →cwnd=10,ack=10 → ....

但由于cwnd还是一直在增长的,总会发生拥塞(丢包,超时重传),这时已经发生拥塞,需要利用拥塞发生的算法解决拥塞。
拥塞发生
当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:
- 超时重传
- 快速重传
超时重传
发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止。重传超时时间RTO
当时间超过RTO还没有收到ACK则执行下面算法:
ssthresh设为cwnd/2,cwnd重置为1
从下图来看,这种方式太”激进“,在7-8轮次,cwnd由12急剧减少到1,传输数据量迅速减少,这会造成网络卡顿。

快速重传
当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。
cwnd = cwnd/2,也就是设置为原来的一半;ssthresh = cwnd;- 进入快速恢复算法
快速恢复 ※

为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。
TCP 的拥塞控制采用了四种算法,即 慢开始 、 拥塞避免 、快重传 和 快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。
- 慢开始: 慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口数值。cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍。
- 拥塞避免: 拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送放的 cwnd 加 1.
- 快重传与快恢复: 在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件指出的数据段丢失了,并立即重传这些丢失的数据段。有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。
#question 快速恢复
TCP UDP比较

UDP
为什么QQ采用UDP协议?
- QQ文件传输是基于TCP的。
- UDP进行交互通信的好处在于,延迟短,对数据丢失的处理比较简单,网络开销小。
- QQ语音与视频,不可靠传输——数据丢失不会重传。如果重传,则会在网络不好的情况下,几秒后再出现丢失的画面,体验不好。
- 服务器压力小
UDP不可靠的原因
UDP 在传输数据之前不需要先建立连接,远地主机的运输层在接收到 UDP 报文后,不需要确认,提供不可靠交付。总结就以下四点:
- 不保证消息交付:不确认,不重传,无超时
- 不保证交付顺序:不设置包序号,不重排,不会发生队首阻塞
- 不跟踪连接状态:不必建立连接或重启状态机
- 不进行拥塞控制:不内置客户端或网络反馈机制
DNS为什么用UDP
DNS什么时候采用tcp协议,什么时候采用udp协议,为什么要这么设计_秃头呆熊的博客-CSDN博客_dns什么时候用tcp什么时候用udp
1.区域传输时,一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息,传输协议是tcp。
2.域名解析时一般返回的内容都不超过512字节,首选的通讯协议是udp。使用udp传输,不用经过TCP三次握手,这样DNS服务器负载更低,响应更快
3.当域名解析的反馈报文的长度超过512字节时,将不能使用udp协议进行解析,此时必须使用tcp。通常传统的UDP报文一般不会大于512字节。
TCP、UDP比较

IP
寻址、路由
寻址是大的宏观的方法论,路由是小的具体的实现。
地址
两个主机之间要进行数据传输,首先要知道双方地址,这是基础,寻址和路由的基础。
基础
Internet Protocol,互联网协议。
位于TCP/IP模型中的第三层——网络层。

网络中源地址IP与目标地址IP不会变,变的是源MAC地址和目标MAC地址。
IPv4地址由32位整数表示。

IP地址的分类
IP 地址分类成了 5 种类型,分别是 A 类、B 类、C 类、D 类、E 类。

A、B、C 分类对应的地址范围、最大主机个数。

计算C类地址最大主机数:$$2^8-2=254$$
为什么-2
在 IP 地址中,有两个 IP 是特殊的,分别是主机号全为 1 和 全为 0 地址。

- 主机号全为 1 指定某个网络下的所有主机,用于广播
- 主机号全为 0 指定某个网络
广播地址用于再同一链路种互相连接的主机之间发送数据包。
如何计算广播地址
172.20.0.0/16 用二进制表示如下:
10101100.00010100.00000000.00000000
将这个地址的主机部分全部改为 1,则形成广播地址:
10101100.00010100.11111111.11111111
再将这个地址用十进制表示,则为 172.20.255.255
IP地址的优缺点
优点:简单明了、选路(基于网络地址)简单。
缺点
同一网络下没有地址层次,比如一个公司里用了 B 类地址,但是可能需要根据生产环境、测试环境、开发环境来划分地址层次,而这种 IP 分类是没有地址层次划分的功能,所以这就缺少地址的灵活性。
A、B、C类有个尴尬处境,就是不能很好的与现实网络匹配。 AB类主机数太多,浪费,C类主机数他少不够用。
无分类地址CIDR
为了解决IP存在的缺点,提出了CIDR。
这种方式不再有分类地址的概念,32 比特的 IP 地址被划分为两部分,前面是网络号,后面是主机号。
表示形式 a.b.c.d/x,其中 /x 表示前 x 位属于网络号, x 的范围是 0 ~ 32,这就使得 IP 地址更加具有灵活性。
表示形式
地址表示
比如 10.100.122.2/24,这种地址表示形式就是 CIDR,/24 表示前 24 位是网络号,剩余的 8 位是主机号。

子网掩码
比如255.255.255.0子网掩码。
将子网掩码与IP地址按位计算AND,即可得到网络号。
将子网掩码和 IP 地址按位计算 AND,就可得到网络号。

为什么分离网络号和主机号
根据网络号判断是否在同一广播域中
怎么子网划分
子网划分实际上将主机地址分为两部分:子网网络地址和子网主机地址。(可以借助子网掩码lai'shi'xi

假设对 C 类地址进行子网划分,网络地址 192.168.1.0,使用子网掩码 255.255.255.192 对其进行子网划分。
C 类地址中前 24 位是网络号,最后 8 位是主机号,根据子网掩码可知从 8 位主机号中借用 2 位作为子网号。

公有IP和私有IP
公有IP不能重复,私有IP是公有IP使用NAT转化为IP地址。
有了地址,两台主机之间虽知道了各自的位置,但它们之间并不是直连的,如何寻找这就是寻址和路由要解决的。
寻址
路由
路由控制 ※
IP地址的网络地址用于进行路由控制。
ICMP
互联网控制报文协议。
ICMP 主要的功能包括:确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。
ICMP 包头格式
ICMP 报文是封装在 IP 包里面,它工作在网络层,是 IP 协议的助手。
ICMP 包头的类型字段,大致可以分为两大类:
- 一类是用于诊断的查询消息,也就是「查询报文类型」
- 另一类是通知出错原因的错误消息,也就是「差错报文类型」
回送消息 —— 类型
0和8
回送消息用于进行通信的主机或路由器之间,判断所发送的数据包是否已经成功到达对端的一种消息,ping 命令就是利用这个消息实现的。
PING的过程
- 构建一个ICMP回送请求数据
- 构建IP数据包
- 添加MAC地址
- 向临近的路由发送
- 如何目标主机可达则发送ICMP回送响应消息
说了这么多,可以看出 ping 这个程序是使用了 ICMP 里面的 ECHO REQUEST(类型为 8 ) 和 ECHO REPLY (类型为 0)。
traceroute原理
充分利用ICMP差错报文类型的应用。
作用
故意设置特殊的TTL,来追踪去往目的地时沿途经过的路由器
原理:
利用IP包的生存期限,从1开始按照顺序递增的同时发送UDP包,强制接受ICMP超时消息的一种方法。将 TTL 设置 为
1,则遇到第一个路由器,就牺牲了,接着返回 ICMP 差错报文网络包,类型是时间超时。如何判断到达目的主机?
发送UDP包时,会填入一个不可能的端口,当目的主机收到UDP包后,返回ICMP差错报文消息,类型是端口不可达。
当报文类型不再是超时,而是端口不可达时,说明UDP包到达目的主机
故意设置部分篇,从而确定路径的MTU。