(三)HTTP/TCP 面试题详解(2024)

739 阅读25分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 3 天,点击查看活动详情

在上一篇,我们讲了很多关于浏览器的问题,其中谈到了很多次HTTPTCP。那么,这一篇,我们就主要来讲讲这些关于计算机网络的相关问题吧 ~

大学期间,计算机网络这一门课上的还是非常的快乐的,记得当时是学院书记带的这门课,在丰富网络理论的同时,经常带我们做团队实践。时间一晃,过去挺久了。

写到这里,发现自己对这一块的认识远远不够清晰完整。于是乎,我想起了《图解 HTTP》这本神作,同时查阅了一些优秀博主的相关文章。非常感谢,实力有限,我们主要针对比较常见的相关面试题来粗糙的整理一下吧 ~

1、HTTP

刚开始设计文章结构的时候,挺痛苦的,不知如何下手。想了半天,还是先来个开胃菜吧 ~

(1)HTTP 的发展

HTTP建立之初:为了将超文本标记语言(HTML)文档从Web服务器传送到客户端

页面复杂化:AJAX的出现,我们又多了一种向服务器端获取数据的方法

移动端:深入HTTP ` ==> 2.0

(2)HTTP 协议简介

HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。(客户端发出请求,服务端进行响应)

HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。

HTTP是不保存状态的协议,既无状态协议,协议本身对于请求或响应之间的通信状态不进行保存,因此连接双方不能知晓对方当前的身份和状态。

这也是Cookie技术产生的重要原因之一:客户端的状态管理

(3)HTTP1.1 相对  HTTP1.0 的一些区别

最早的HTTP只是使用在一些较为简单的网页上和网络请求上,所以比较简单,每次请求都打开一个新的TCP链接,收到响应之后立即断开连接。

主要区别:

  • 缓存策略:在HTTP1.0中主要使用header里的If-Modified-SinceExpires来做为缓存策略,HTTP1.1则引入了Entity tagIf-Match等更多可供选择的缓存头来控制缓存策略。
  • 带宽优化及网络连接的使用:HTTP1.0中存在一些浪费带宽的现象,且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  • 错误通知的管理:HTTP1.1中新增了 24 个错误状态响应码
  • Host头处理:在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,HTTP/1.1的请求消息和响应消息都包含Host头部,以区分同一个物理主机中的不同虚拟主机的域名
  • 长连接:HTTP1.0每次请求都要创建连接,HTTP 1.1支持长连接和请求的流水线处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟(Connection: keep-alive

(4)HTTP2.0 和 HTTP1.X 相比的新特性

新二进制格式:

了解该特性前,我们先看看HTTP2.0中三个非常重要的概念:

  • 帧:即二进制帧,是HTTP2.0中的数据通信(流中)的最小单位
  • 消息:消息是指逻辑上的HTTP消息(请求/响应)。一系列数据帧组成了一个完整的消息。
  • 流:  流是连接中的一个虚拟信道,可以承载双向消息传输。每个流有唯一整数标识符。

HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多。而HTTP 2.0将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码,二进制只有 0 和 1 的组合,解析起来方便且健壮。

多路复用:

HTTP 2.0的多路复用其实是HTTP 1.1中长连接的升级版本。

HTTP 1.1中,想并发多个请求,必须使用多个TCP连接。且一次请求与响应的交互必须要等待前面的请求交互完成,否则后面的只能等待(线头阻塞)。

HTTP 2.0中,多路复用允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了线头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能。

more:

  • 同域名下所有通信都在单个连接上完成。
  • 单个连接可以承载任意数量的双向数据流。
  • 数据流以消息的形式发送,而消息⼜由⼀个或多个帧组成,多个帧之间可以乱序发送,因为根据帧⾸部的流标识可以重新组装

头部压缩:

HTTP1.x的头部带有大量头部数据,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的头部大小,通讯双方各自存储一份头部表,既避免了重复头部的传输,又减小了需要传输的大小。

你可以理解为只发送差异数据,⽽不是全部发送,从⽽减少头部的信息量

服务端推送:

服务端可以根据客户端的请求,提前返回多个响应,推送额外的资源给客户端(客户端可以选择不需要服务端的推送)。例如服务端可以主动把JSCSS文件推送给客户端,而不需要客户端解析 HTML 时在重复发送这些请求。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度

More:可能你还想知道更多的HTTPHTTPS的区别

  • HTTP是明文传输,HTTPS是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全
  • HTTPS对搜索引擎更友好,利于SEO(如谷歌、百度优先索引HTTPS网页)
  • HTTPS标准端口 443,HTTP标准端口 80
  • HTTPS基于传输层,HTTP基于应用层
  • HTTPS在浏览器显示绿色安全锁,HTTP没有显示

咳咳,其实还有一个区别,就是,HTTPS申请比较麻烦,而且,而且,还要钱,好贵哦!

(5)请求方法

  • GET:请求服务器发送某些资源
  • HEAD:请求资源的头部信息,并且这些头部与HTTP GET方法请求时返回的⼀致(如在下载⼀个大文件前先获取其大小再决定是否要下载,以此可以节约带宽资源)
  • OPTIONS:获取目的资源所支持的通信选项
  • POST:发送数据给服务器
  • PUT:新增资源或者使用请求中的有效负载替换目标资源的表现形式
  • DELETE:删除资源
  • PATCH:用于对资源进行部分修改
  • CONNECTHTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
  • TRACE:回显服务器收到的请求,主要⽤于测试或诊断

说到请求方法,咱们就不得不提一下其中GETPOST的区别:

  • 数据传输方式:GET请求通过URL传输数据,而POST的数据通过请求主体传输。
  • 安全性:POST的数据因为在请求主体内,所以有⼀定的安全性保证,而GET的数据在URL中,通过历史记录或缓存很容易查到数据信息。
  • 数据类型:GET只允许ASCII字符,而POST⽆限制
  • GET无害: 刷新、后退等浏览器操作GET请求是⽆害的,POST可能重复提交表单
  • 特性:GET是安全(指只读性,使用这个方法不会引起服务器状态变化)且幂等(指同⼀个请求方法调用⼀次或多次执行的效果相同),而POST是非安全非幂等

可能你还会注意到,POSTPUT都是给服务器发送新的资源,有什么区别呢?

  • 根本区别:POST方法是幂等的,连续调用一次或多次效果相同(无副作用),而PUT方法是非幂等的
  • PUTURI指向具体单一资源,而POST可以指向资源集合

PUTPATCH都是给服务器发送修改资源,又有什么区别呢?

  • PUTPATCH都是更新资源,而PATCH用来对已知资源进行局部更新

(6)HTTP 报文

用于HTTP协议交互的信息被称为HTTP报文。客户端的HTTP报文 叫请求报文,服务端的HTTP报文叫响应报文。

请求报文

  • 请求行:请求方法、协议版本
  • 请求头部:请求URI、客户端信息等
  • 空行:回车符、换行符
  • 请求体:用户信息和资源信息等

image.png

响应报文

  • 响应行:协议版本、状态码
  • 响应头:服务器名称、资源标识等
  • 空行:回车符、换行符
  • 响应体:服务端返回的资源信息

image.png

(7)HTTP 首部

这部分表格是某位优秀博主的杰作,已经非常清晰全面了,感谢大佬的分享!我这里根据自己的理解做了适当的修改,作为自己未来可能用到的一份资料。

这部分其实面试一般不太会涉及,大家留个印象即可,必要时再返回来细细探究吧 ~

通用首部

通用首部作用(请求报文和响应报文都可能使用)有效
Cache-Control控制缓存的行为:no-cache(强制向服务器再次验证)、no-store(不做任何缓存)、 max-age=111111(资源可缓存最大时间 秒)、public(客户端、代理服务器都可 利用缓存)、private(代理服务器不可用缓存)Last-Modified/Etag
Connection浏览器想要优先使用的连接类型: keep-alive close(开启和关闭持久(长)连接)有效
Date创建报文的日期有效
Pragma只用于请求报文,客户端要求中间服务器不返回缓存的资源有效
Via代理服务器相关信息,每经过一个代理服务器就会添加相关信息,用逗号分割有效
Transfer-Encoding报文主体的传输编码格式:chunked 分块传输无效
Upgrade要求客户端使用的升级协议,需配合 Connection: Upgrade 一起使用:websocket
Warning缓存相关问题的警告

请求首部

请求首部作用(客户端向服务端发送请求报文专用)有效
Accept能正确接收的媒体类型:application/json text/plainLast-Modified/Etag
Accept-Charset能正确接收的字符集: unicode-1-1有效
Accept-Encoding能正确接收的编码格式列表:gzip deflate有效
Accept-Language能正确接收的语言列表:zh-cn,zh;1=0.9,en,1=0.8有效
Authorization客户端认证信息:Bearer dSdSdFFlsfdjasd123,一般存 token 用有效
Cookie发送给服务器的 Cookie 信息无效
Expect期待服务端的指定行为
From请求方邮箱地址
Host服务器的域名,用于区分单台服务器多个域名的虚拟主机,是 HTTP/1.1 唯一必须包含的字段。
If-Match比较实体标记(ETag):两端资源标记比较,只有判断条件为真服务端才会接受请求:If-Mach: "123456,和服务端文件标记比较
If-Modified-Since比较资源更新时间,本地资源未修改返回 304(比较时间)
If-None-Match与 If-Match 相反,本地资源未修改返回 304(比较标记)
User-Agent客户端信息
Max-Forwards限制可被代理及网关转发的次数
Proxy-Authorization向代理服务器发送验证信息
Range请求某个内容的一部分,配合 If-Range 使用
Referer请求发起页面的原始 URI
TE传输编码优先级

响应首部

响应首部作用(服务器向客户端响应报文专用)
Accept-Ranges告知客户端服务器是否可接受范围请求,是 bytes,否 none
Age资源在代理缓存中存在的时间
ETag表示资源唯一的标识,资源发生变化时标识也会发生改变
Location客户端重定向到某个 URL
Proxy-Authenticate需要向代理服务器发送验证信息
Server服务器信息:如 Apache Nginx
WWW-Authenticate获取服务器资源需要客户端认证的方案
Set-Cookie需要存在客户端的信息,一般用于识别用户身份

实体首部

实体首部作用(补充请求报文或响应报文相关信息)
Allow资源可支持的请求方式:GET HEAD POST
Content-Encoding实体内容的编码格式:gzip deflate
Content-Language实体内容使用的语言:zh-CN
Content-Lengthrequest body 长度(即实体主体的大小):
Content-Location返回数据的备用地址
Content-MD5Base64 加密格式的内容 MD5 检验值
Content-Range响应主体的内容范围
Content-Type实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求)
Expires实体内容的过期时间
Last_modified实体内容的最后修改时间

(8)状态码

来啦来啦,它们来啦!必考的状态码,终于出场啦!给我冲 ~

2XX

2XX成功(这系列表明请求被正常处理了)
200OK,客户端发来的请求在服务器端被正确处理
201Created 请求已经被实现,且有一个新的资源已经依据请求的需要而建立
202Accepted 请求已经被实现
204No Content,表示请求成功,但响应报文不含实体的主体部分
206Partial Content,进行范围请求成功
Content-MD5Base64 加密格式的内容 MD5 检验值
Content-Range响应主体的内容范围
Content-Type实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求)
Expires实体内容的过期时间
Last_modified实体内容的最后修改时间

3XX

3XX重定向(表明浏览器要执行特殊处理)
301Moved Permanently,永久性重定向,表示资源已被分配了新的 URL
302Found,临时性重定向,表示资源临时被分配了新的 URL
303See Other,表示资源存在着另一个 URL,应使用 GET 方法获取资源(对于 301/302/303 响应,几乎所有浏览器都会删除报文主体并自动用 GET 重新请求)
304Not Modified,表示服务器允许访问资源,但请求未满足条件的情况(与重定向无关)
307Temporary Redirect,临时重定向,和 302 含义类似,但是期望客户端保持请求方法不变向新的地址发出请求
Content-MD5Base64 加密格式的内容 MD5 检验值
Content-Range响应主体的内容范围
Content-Type实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求)
Expires实体内容的过期时间
Last_modified实体内容的最后修改时间

4XX

4XX客户端错误
400Bad Request,请求报文存在语法错误
401Unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息
403Forbidden,表示对请求资源的访问被服务器拒绝,可在实体主体部分返回原因描述
404Not Found,表示在服务器上没有找到请求的资源
408Request Timeout,客户端请求超时
409Conflict,请求的资源可能引起冲突
Content-Range响应主体的内容范围
Content-Type实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求)
Expires实体内容的过期时间
Last_modified实体内容的最后修改时间

5XX

5XX服务器错误
500Internal sever error,表示服务器端在执行请求时发生了错误
501Not Implemented,表示服务器不支持当前请求
503service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求
505Http version not supported,服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本
408Request Timeout,客户端请求超时
409Conflict,请求的资源可能引起冲突
Content-Range响应主体的内容范围
Content-Type实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求)
Expires实体内容的过期时间
Last_modified实体内容的最后修改时间

(9)HTTP 的   keep-alive

其实这个东西在前面讲HTTP1.1HTTP1.0的区别中提到过,就是开启长连接的方式。

我们知道,在HTTP1.0中,每次发起HTTP请求都要创建连接,而HTTP 1.1引入了长连接机制,在HTTP请求头中加入了Connection:keep-alive,告诉对方请求响应完成后不要关闭,后续还要用这个请求继续交互。这样就在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。

我们再来剖析一下keep-alive的一些优点

  • 较少的CPU和内存的使用(由于同时打开的连接减少了)
  • 允许请求和应答的HTTP管线化
  • 降低拥塞控制 (TCP连接减少了)
  • 减少了后续请求的延迟(无需再进行握手)
  • 报告错误无需关闭TCP

HTTP我们有个清晰的了解后,我相信你一定会疑惑,那HTTPS又是什么,他们之间有什么区别和联系呢?

2、HTTPS

(1)什么是 HTTPS

HTTPS = HTTP + TLS/SSLHTTPS是在HTTP上建立TLS/SSL协议加密层的安全版的HTTP

image-20220414110028936

(2)为什么需要 HTTPS 呢

总体原因:HTTP协议中可能存在数据盗取或者身份伪装等安全性问题

HTTP问题剖析:

数据未加密,会被盗取

HTTP本身不具备加密的功能,所以无法做到对通信数据进行加密

数据完整性无法保证,会被篡改

HTTP无法验证通信数据是否准确完整,无法确认请求和响应过程中的数据是否被篡改

通信双方身份无验证,会被伪装

HTTP没有验证通信方的过程,任何人都可以发起请求或伪装成服务端,进而欺骗用户

(3)那 HTTPS 是如何解决 HTTP 上述问题的

痛点解决:

  • 数据加密
  • 完整性校验
  • 身份验证

HTTPS协议的主要功能基本都依赖于TLS/SSL协议,TLS/SSL的功能实现主要依赖于三类基本算法: 对称加密、Hash函数、非对称加密

  • 对称加密算法采用密钥协商对数据加密
  • 基于Hash函数验证数据的完整性
  • 非对称加密实现身份验证和密钥协商

1、数据加密问题

方法 1:对称加密

加密和解密同用一个密钥。

Bug:任何人只要持有密钥就能解密,而且如何安全地转交和保管密钥呢?

方法 2:非对称加密

组成:公钥 + 私钥 = 密钥对

通信特点:

  • 公钥是公开的密钥,任何人可以获得;私钥只有自己知道(一对多)
  • 公钥加密的数据,只有它对应的私钥可以解密;私钥加密的数据,只有它对应的公钥可以解密

潜在优势:

  • 只有自己(服务器)有私钥,所以服务器发出的数据不可能被伪造。强行伪造的后果是客户端用公钥无法解开
  • 只有自己(服务器)有私钥,任何人用公钥加密的数据都是绝对安全的,也就是只有真正的服务器可以解密数据

通信过程:

  • 通信 A、B 都有一套自己的密钥对,A 通信之前都会先把自己的公钥发送给 B
  • B 给拿到的公钥进行加密,响应数据给 A,A 再用自己的私钥,对携带加密过的自己的公钥的响应数据进行解密

可能这样能够理解的更人性化一点:

  1. 客户端:Hello,我要发起一个HTTPS请求了,这是我的 (用公钥加密后的) 秘钥哦!
  2. 服务器:好勒,我知道你的秘钥了,后续就用它传输数据给你啦!

嘿嘿,写到这里,我突然发出了一声“哦豁”!旁边同事问我怎么了,我脑海里瞬间冒出一个东西,这怎么像极了TCP的三次握手哇?

image-20220414105814608

妙哇妙哇!真是精彩绝伦的知识哇!~ 但是不要高兴的太早哦,它还有 Bug。

Bug:

  • 私钥对数据加密了,但是公钥是公开的,别人拿到私钥加密的数据后就可以通过公钥来破解。
  • 公钥并不包含服务器的信息,使用非对称加密算法无法确保服务器身份的合法性,存在中间人攻击的风险,服务器发送给客户端的公钥可能在传送过程中被中间人截获并篡改
  • 使用非对称加密在数据加密解密过程需要消耗一定时间,降低了数据传输效率

What?对称不行,非对称也不行,你说怎么样才行?

别急,经过我们的仔细观察,我们可以发现:

  • 使用对称密钥的好处是解密的效率比较快
  • 使用非对称密钥的好处是可以使得传输的内容不能被破解

方法 3:对称加密+非对称加密(HTTPS 采用这种方式)

通信过程:

  • 使用对称加密的密钥 λ(加密和解密共用同一个)
  • A 使用非对称加密的公钥对  λ 加密,发送给 B,B 使用自己的非对称加密的私钥对  λ 解密拿到  λ,确保双方使用的密钥都是  λ 后,以对称加密的方式进行通信。

Bug:

传输过程中可能经过很多中间节点,虽然数据无法被解密,但可能被篡改,那如何校验数据的完整性呢?

2、完整性校验问题

数字签名:

  • 能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名。
  • 数字签名能确定消息的完整性,证明数据是否未被篡改过。

数字签名是如何生成的?

image-20220414110615998

将一段数据先用 Hash 函数生成消息摘要,然后用发送方的私钥加密生成数字签名,与原文一起传送给接收方。

接收方如何验证数字签名?

image-20220414110752921

​   简单理一下验证流程:

  1. 首先接收方拿到发送方的公钥,破解数字签名得到消息摘要
  2. 同时用 Hash 函数对收到的数据生成一个消息摘要
  3. 对比两个消息摘要是否相同,相同则收到的信息完整

Bug:

如果此时,在 接收方(A)、发送方(B)之间存在一个中间人,他把原本双方通信互发的公钥,换成自己的,这样中间人就可以解密通信双方发生的所有数据了。

好家伙,还来,套娃呢,你这么牛不给你颁发个 NB 证书?

是的,就是证书,你要的来了。

3、身份验证问题

典型的密码学中的身份验证问题:公钥被调包,客户端无法分辨传回公钥的是中间人还是服务器

HTTPS中,我们使用数字证书来解决这个问题。

数字证书 = 数据信息 + 数字签名

显而易见,核心还是数字签名,具体其实和上一小问一样,这里不再重复啦!不过不得不提的是里面强大的哈希(Hash)算法了。从函数角度来看,不管多复杂的数据(定义域可以非常大)经过哈希算法后都会得到一个值,而且这个值处在某个特定(远小于定义域的范围)值域内。相同数据的哈希结果一定相同(排除小概率的哈希冲突哈哈哈哈)。

为了确保我们的证书没有被篡改,我们在传递证书的同时会传递对应的哈希值(消息摘要)。

关于数字证书,我们就需要通过数字证书认证机构(CA)来申请认证啦!

皮一下,很开心!有没有可能同时修改了数字证书和公钥呢?原谅笔者太菜了,触及不到这个层面。如果你有办法,请不吝赐教 ~

最后我们再总结一下:

HTTPS就是基于HTTP,使用SSL/TLS协议进行加密传输,让客户端拿到服务器的公钥,然后客户端随机生成一个对称加密的秘钥 λ,使用公钥加密 λ,再传输给服务端,后续的所有信息都通过该对称秘钥 λ 进行加密解密,完成整个HTTPS的流程。

(4)关于 HTTPS 的性能疑虑

HTTPS 增加的时间主要花费在两组SSL`之间的耗时和证书的读取验证上,而对称算法的加解密时间几乎可以忽略不计。

一般只有首次握手才是一次完整的握手过程,后续请求可以通过客户端把上一次的加密情况返回给服务器,继续通信。

而且不要忘了HTTPS2.0的多个新特性,这些技术对性能的提升可不是闹着玩的喔 ~

3、TCP

写到这里,已经在公司待到晚上十点半了,说实话,关于TCP的内容,我的脑海里,除了三次握手和四次挥手,已经所剩无几了。相信大多数前端打工人,遇到关于TCP的面试题,也都停留于此。我还是忍不住去查看一些优秀大佬的文章,发现TCP的强大真的远不止如此 ~~~ 我更想把这个标题更改为TCP/IP协议。

实力和精力有限,这里我先列出几篇优秀的大佬文章,以及几个重要考点,后续会转回来继续探究这块大大的肥肉 ~~~

OSI 体系结构

七层由上到下:

  • 应用层
  • 表示层
  • 会话层
  • 传输层
  • 网络层
  • 数据链层
  • 物理层

TCP 与 UDP

两个都是传输层提供的到达目标网络的方式

传输控制协议(TCP):

  • 面向连接协议
  • 数据大小无限制
  • 速度慢,但是可靠性高

用户数据报协议(UDP):

  • 无连接协议
  • 数据大小有限制(64k)
  • 速度快,但可靠性低

TCP 的三次握手和四次挥手

三次握手:

  1. 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,等待服务器确认
  2. 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,
  3. 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入 ESTABLISHEDTCP连接成功)状态,完成三次握手

面试时可这样讲述:

  1. 第一次握手:由浏览器发起,告诉服务器我要发送请求了
  2. 第二次握手:由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧
  3. 第三次握手:由浏览器发送,告诉服务器,我马上就发了,准备接受吧

面试官可能还问你,为什么需要三次握手?----  为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

四次挥手:

  1. 第一次挥手:客户端进程发出连接释放报文(FIN报文),并且停止发送数据
  2. 第二次挥手:服务器收到连接释放报文,发出确认报文,ACK=1ack=u+1,并且带上自己的序列号seq=v 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(`终止等待 2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)
  3. 第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1ack=u+1
  4. 第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,ACK=1ack=w+1,而自己的序列号是 seq=u+1。服务器只要收到了客户端发出的确认,立即进入CLOSED状态。