一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 3 天,点击查看活动详情。
在上一篇,我们讲了很多关于浏览器的问题,其中谈到了很多次
HTTP、TCP。那么,这一篇,我们就主要来讲讲这些关于计算机网络的相关问题吧 ~
大学期间,计算机网络这一门课上的还是非常的快乐的,记得当时是学院书记带的这门课,在丰富网络理论的同时,经常带我们做团队实践。时间一晃,过去挺久了。
写到这里,发现自己对这一块的认识远远不够清晰完整。于是乎,我想起了《图解 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-Since、Expires来做为缓存策略,HTTP1.1则引入了Entity tag、If-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来减少需要传输的头部大小,通讯双方各自存储一份头部表,既避免了重复头部的传输,又减小了需要传输的大小。
你可以理解为只发送差异数据,⽽不是全部发送,从⽽减少头部的信息量
服务端推送:
服务端可以根据客户端的请求,提前返回多个响应,推送额外的资源给客户端(客户端可以选择不需要服务端的推送)。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析 HTML 时在重复发送这些请求。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度
More:可能你还想知道更多的HTTP与HTTPS的区别
HTTP是明文传输,HTTPS是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全HTTPS对搜索引擎更友好,利于SEO(如谷歌、百度优先索引HTTPS网页)HTTPS标准端口 443,HTTP标准端口 80HTTPS基于传输层,HTTP基于应用层HTTPS在浏览器显示绿色安全锁,HTTP没有显示
咳咳,其实还有一个区别,就是,HTTPS申请比较麻烦,而且,而且,还要钱,好贵哦!
(5)请求方法
- GET:请求服务器发送某些资源
- HEAD:请求资源的头部信息,并且这些头部与
HTTP GET方法请求时返回的⼀致(如在下载⼀个大文件前先获取其大小再决定是否要下载,以此可以节约带宽资源) - OPTIONS:获取目的资源所支持的通信选项
- POST:发送数据给服务器
- PUT:新增资源或者使用请求中的有效负载替换目标资源的表现形式
- DELETE:删除资源
- PATCH:用于对资源进行部分修改
- CONNECT:
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 - TRACE:回显服务器收到的请求,主要⽤于测试或诊断
说到请求方法,咱们就不得不提一下其中GET和POST的区别:
- 数据传输方式:
GET请求通过URL传输数据,而POST的数据通过请求主体传输。 - 安全性:
POST的数据因为在请求主体内,所以有⼀定的安全性保证,而GET的数据在URL中,通过历史记录或缓存很容易查到数据信息。 - 数据类型:
GET只允许ASCII字符,而POST⽆限制 GET无害: 刷新、后退等浏览器操作GET请求是⽆害的,POST可能重复提交表单- 特性:
GET是安全(指只读性,使用这个方法不会引起服务器状态变化)且幂等(指同⼀个请求方法调用⼀次或多次执行的效果相同),而POST是非安全非幂等
可能你还会注意到,
POST和PUT都是给服务器发送新的资源,有什么区别呢?
- 根本区别:
POST方法是幂等的,连续调用一次或多次效果相同(无副作用),而PUT方法是非幂等的 PUT的URI指向具体单一资源,而POST可以指向资源集合
PUT和PATCH都是给服务器发送修改资源,又有什么区别呢?
PUT和PATCH都是更新资源,而PATCH用来对已知资源进行局部更新
(6)HTTP 报文
用于HTTP协议交互的信息被称为HTTP报文。客户端的HTTP报文 叫请求报文,服务端的HTTP报文叫响应报文。
请求报文
- 请求行:请求方法、协议版本
- 请求头部:请求
URI、客户端信息等 - 空行:回车符、换行符
- 请求体:用户信息和资源信息等
响应报文
- 响应行:协议版本、状态码
- 响应头:服务器名称、资源标识等
- 空行:回车符、换行符
- 响应体:服务端返回的资源信息
(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/plain | Last-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-Length | request body 长度(即实体主体的大小): |
| Content-Location | 返回数据的备用地址 |
| Content-MD5 | Base64 加密格式的内容 MD5 检验值 |
| Content-Range | 响应主体的内容范围 |
| Content-Type | 实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求) |
| Expires | 实体内容的过期时间 |
| Last_modified | 实体内容的最后修改时间 |
(8)状态码
来啦来啦,它们来啦!必考的状态码,终于出场啦!给我冲 ~
2XX
| 2XX | 成功(这系列表明请求被正常处理了) |
|---|---|
| 200 | OK,客户端发来的请求在服务器端被正确处理 |
| 201 | Created 请求已经被实现,且有一个新的资源已经依据请求的需要而建立 |
| 202 | Accepted 请求已经被实现 |
| 204 | No Content,表示请求成功,但响应报文不含实体的主体部分 |
| 206 | Partial Content,进行范围请求成功 |
| Content-MD5 | Base64 加密格式的内容 MD5 检验值 |
| Content-Range | 响应主体的内容范围 |
| Content-Type | 实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求) |
| Expires | 实体内容的过期时间 |
| Last_modified | 实体内容的最后修改时间 |
3XX
| 3XX | 重定向(表明浏览器要执行特殊处理) |
|---|---|
| 301 | Moved Permanently,永久性重定向,表示资源已被分配了新的 URL |
| 302 | Found,临时性重定向,表示资源临时被分配了新的 URL |
| 303 | See Other,表示资源存在着另一个 URL,应使用 GET 方法获取资源(对于 301/302/303 响应,几乎所有浏览器都会删除报文主体并自动用 GET 重新请求) |
| 304 | Not Modified,表示服务器允许访问资源,但请求未满足条件的情况(与重定向无关) |
| 307 | Temporary Redirect,临时重定向,和 302 含义类似,但是期望客户端保持请求方法不变向新的地址发出请求 |
| Content-MD5 | Base64 加密格式的内容 MD5 检验值 |
| Content-Range | 响应主体的内容范围 |
| Content-Type | 实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求) |
| Expires | 实体内容的过期时间 |
| Last_modified | 实体内容的最后修改时间 |
4XX
| 4XX | 客户端错误 |
|---|---|
| 400 | Bad Request,请求报文存在语法错误 |
| 401 | Unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息 |
| 403 | Forbidden,表示对请求资源的访问被服务器拒绝,可在实体主体部分返回原因描述 |
| 404 | Not Found,表示在服务器上没有找到请求的资源 |
| 408 | Request Timeout,客户端请求超时 |
| 409 | Conflict,请求的资源可能引起冲突 |
| Content-Range | 响应主体的内容范围 |
| Content-Type | 实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求) |
| Expires | 实体内容的过期时间 |
| Last_modified | 实体内容的最后修改时间 |
5XX
| 5XX | 服务器错误 |
|---|---|
| 500 | Internal sever error,表示服务器端在执行请求时发生了错误 |
| 501 | Not Implemented,表示服务器不支持当前请求 |
| 503 | service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求 |
| 505 | Http version not supported,服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本 |
| 408 | Request Timeout,客户端请求超时 |
| 409 | Conflict,请求的资源可能引起冲突 |
| Content-Range | 响应主体的内容范围 |
| Content-Type | 实体内容的媒体类型(如'application/json;charset=UTF-8'则会发送预检请求) |
| Expires | 实体内容的过期时间 |
| Last_modified | 实体内容的最后修改时间 |
(9)HTTP 的 keep-alive
其实这个东西在前面讲HTTP1.1和HTTP1.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/SSL:HTTPS是在HTTP上建立TLS/SSL协议加密层的安全版的HTTP
(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 再用自己的私钥,对携带加密过的自己的公钥的响应数据进行解密
可能这样能够理解的更人性化一点:
- 客户端:Hello,我要发起一个
HTTPS请求了,这是我的 (用公钥加密后的) 秘钥哦! - 服务器:好勒,我知道你的秘钥了,后续就用它传输数据给你啦!
嘿嘿,写到这里,我突然发出了一声“哦豁”!旁边同事问我怎么了,我脑海里瞬间冒出一个东西,这怎么像极了TCP的三次握手哇?
妙哇妙哇!真是精彩绝伦的知识哇!~ 但是不要高兴的太早哦,它还有 Bug。
Bug:
- 私钥对数据加密了,但是公钥是公开的,别人拿到私钥加密的数据后就可以通过公钥来破解。
- 公钥并不包含服务器的信息,使用非对称加密算法无法确保服务器身份的合法性,存在中间人攻击的风险,服务器发送给客户端的公钥可能在传送过程中被中间人截获并篡改
- 使用非对称加密在数据加密解密过程需要消耗一定时间,降低了数据传输效率
What?对称不行,非对称也不行,你说怎么样才行?
别急,经过我们的仔细观察,我们可以发现:
- 使用对称密钥的好处是解密的效率比较快
- 使用非对称密钥的好处是可以使得传输的内容不能被破解
方法 3:对称加密+非对称加密(HTTPS 采用这种方式)
通信过程:
- 使用对称加密的密钥 λ(加密和解密共用同一个)
- A 使用非对称加密的公钥对 λ 加密,发送给 B,B 使用自己的非对称加密的私钥对 λ 解密拿到 λ,确保双方使用的密钥都是 λ 后,以对称加密的方式进行通信。
Bug:
传输过程中可能经过很多中间节点,虽然数据无法被解密,但可能被篡改,那如何校验数据的完整性呢?
2、完整性校验问题
数字签名:
- 能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名。
- 数字签名能确定消息的完整性,证明数据是否未被篡改过。
数字签名是如何生成的?
将一段数据先用 Hash 函数生成消息摘要,然后用发送方的私钥加密生成数字签名,与原文一起传送给接收方。
接收方如何验证数字签名?
简单理一下验证流程:
- 首先接收方拿到发送方的公钥,破解数字签名得到消息摘要
- 同时用 Hash 函数对收到的数据生成一个消息摘要
- 对比两个消息摘要是否相同,相同则收到的信息完整
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 的三次握手和四次挥手
三次握手:
- 第一次握手:建立连接时,客户端发送
syn包(syn=x)到服务器,等待服务器确认 - 第二次握手:服务器收到
syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包, - 第三次握手:客户端收到服务器的
SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手
面试时可这样讲述:
- 第一次握手:由浏览器发起,告诉服务器我要发送请求了
- 第二次握手:由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧
- 第三次握手:由浏览器发送,告诉服务器,我马上就发了,准备接受吧
面试官可能还问你,为什么需要三次握手?---- 为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
四次挥手:
- 第一次挥手:客户端进程发出连接释放报文(
FIN报文),并且停止发送数据 - 第二次挥手:服务器收到连接释放报文,发出确认报文,
ACK=1,ack=u+1,并且带上自己的序列号seq=v客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(`终止等待 2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据) - 第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,
FIN=1,ack=u+1 - 第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,
ACK=1,ack=w+1,而自己的序列号是seq=u+1。服务器只要收到了客户端发出的确认,立即进入CLOSED状态。