😱 一、五层因特网协议栈
协议栈 | 含义 | 举例 | 数据单位封装 |
---|---|---|---|
应用层 | 为操作系统或网络应用程序提供访问网络服务的接口;数据格式转换、数据流动的逻辑通路、数据分割等 | DNS 域名系统、 http 超文本传输协议、 FTP 、 SMTP |
报文(message):网络中交换与传输的数据单元 |
传输层 | 定义端口,标识应用程序身份,实现端口到端口的通信,TCP 协议可以保证数据传输的可靠性 | TCP 传输控制协议、 UDP 用户数据协议 |
报文段(segment)是组成报文的每个分组 |
网络层 | 地址管理与路由选择。定义 IP 地址,区分网段,子网内 MAC 寻址,对外网数据包进行路由转发 | IP 协议、 ARP 地址解析协议(映射 IP 地址与 Mac 地址)、路由器 |
分组(packet):传输的二进制格式单元。数据报(Datagram):传输的基本数据单元。数据包(datapacket):传输中的数据单位。 |
数据链路层 | 对 0 和 1 进行分组,定义数据帧,确认主机的 Mac 地址 | Wi-Fi,以太网:规定一组电信号就是一个数据包,即一帧 | 帧(frame):数据链路层的协议数据单元。 |
物理层 | 界定连接器、数据速率、媒体对应的比特编码方式 | 光纤、双绞线、无线电波:决定电信号(0 和 1)的传输方式、带宽、速率、抗干扰性等 | 比特(bit),协议数据单元。1 字节(byte) = 8 bit |
🍤二、DNS
DNS 的作用就是通过域名查询到具体的
IP
访问www.google.com
时,操作系统执行DNS
递归或迭代查询
- 搜索浏览器 DNS 缓存->操作系统的 DNS 缓存-> 操作系统的 hosts 文件->本地 DNS 服务器->根域名服务器->顶级域名服务器->权威域名服务器
- 直至找到一个或一组 IP 地址,操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来
💭三、HTTP
HTTP 超文本传输协议:无状态协议,不会保存状态
1、资源
1.1 MIME 类型及 Content-Type
MIME(Multipurpose Internet Mail Extension 多用途因特网邮件扩展)媒体类型是一种表示文档、文件或字节流的性质及格式的标准(比如,text/html、image/jpeg)。
浏览器通常使用 MIME 类型(而不是文件扩展名)来确定如何处理 URL,因此 Web 服务器在响应头中添加正确的 MIME 类型非常重要。在 HTTP 中,MIME 媒体类型被广泛用于 Content-Type 和 Accept 首部,例如:
- Content-Type: video/quicktime
- Content-Type: text/html; charset=”iso-8859-6”
- Content-Type: multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p
- Accept: image/gif
常见 Content-Type:
- application/json: JSON 数据格式
- application/pdf:pdf 格式
- application/msword : Word 文档格式
- application/x-www-form-urlencoded :
<form encType=””>
中默认的 encType,form 表单数据被编码为 key/value 格式发送到服务器(表单默认的提交数据的格式) - application/octet-stream :应用程序文件的默认值, 二进制流数据(如常见的文件下载)
- multipart/form-data :表单中进行文件上传使用的格式
1.2 URL(Uniform Resource Locator)统一资源定位符
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
- scheme 方案:访问服务器以获取资源时要使用哪种协议。如
http
、https
- host 主机:资源宿主服务器的主机名或点分 IP 地址
- localhost 是个域名,可被配置为任意的 IP 地址
- 通常指向 127.0.0.1(ipv4)、 ::1(ipv6)表示本地主机名
- 本机 IP 是你真实网卡的 IP,具体来说有线网卡 ethrtnet、无线网卡 wlan。而 127.0.0.1 是那块叫做 loopback 的虚拟网卡的 IP
- localhost 是个域名,可被配置为任意的 IP 地址
- port 端口:资源宿主服务器正在监听的端口号。很多方案都有默认端口号(HTTP 的默认端口号为
80
) - path 路径:服务器上资源的本地名,
/
与前面的 URL 组件分隔开来
2、HTTP 请求方法
副作用:指对服务器上的资源做改变。搜索是无副作用的,注册是副作用的
幂等:指发送 M 和 N 次请求(M 不等于 N,都大于 1),服务器上资源的状态一致
- GET:请求服务器向客户端发送命名资源
- 多用于无副作用,幂等的场景,例如搜索关键字
- Get 请求都包含在 URL 里,能缓存且会被浏览器保存历史纪录
- 只支持 ASCII 字符
- POST:将客户端数据发送到一个服务器网关应用程序
- 多用于副作用,不幂等的场景,例如注册
- 可通过 request body 来传输比 Get 更多的数据
- 支持更多的编码类型且不对数据类型限制
- HEAD:仅发送命名资源响应(同 GET)中的 HTTP 首部
- 多用于在下载一个大文件前,先获取其大小再决定是否要下载
- OPTIONS:用于获取目的资源所支持的通信选项
- PUT:将来自客户端的数据存储到一个命名的服务器资源中
- 多用于幂等的场景,通常情况下,PUT 的 URI 指向是具体单一资源
- DELETE:从服务器中删除命名资源
- PATCH:用于对资源进行部分修改
3、HTTP 响应状态码
- 2XX 成功
- 200 OK
- 204 No Content 响应报文不含实体的主体部分
- 205 Reset Content 响应报文不含实体的主体部分,要求请求方重置内容
- 206 Partial Content 进行范围请求
- 3XX 重定向
- 301 Moved Permanently 永久性重定向,表示资源已被分配了新的 URL
- 302 found 临时性重定向,表示资源临时被分配了新的 URL(http1.0 协议)
- 303 see other 表示资源存在着另一个 URL,应使用 GET 方法获取资源
- 304 not modified 服务器允许访问资源,但请求未满足条件(资源未修改)
- 307 temporary redirect 临时重定向,期望客户端保持请求方法不变向新地址请求
- 4XX 客户端错误
- 400 bad request 请求报文存在语法错误
- 401 unauthorized 表示发送的请求需要有通过 HTTP 认证的认证信息
- 403 forbidden 表示对请求资源的访问被服务器拒绝
- 404 not found 表示在服务器上没有找到请求的资源
- 5XX 服务器错误
- 500 internal sever error,表示服务器端在执行请求时发生了错误
- 501 Not Implemented,请求超出服务器的能力范围(不支持的请求方法)
- 503 service unavailable,服务器暂时处于超负载或停机维护,无法处理请求
- 504 Gateway Timeout,响应来自一个网关或代理,它们在等待另一服务器对其请求进行响应时超时
4、HTTP 首部
- General
- Connection:浏览器想要优先使用的连接类型,比如
keep-alive
长连接 - Date:创建报文时间,比如
Thu, 10 Oct 2019 10:47:45 GMT
- Transfer-Encoding:传输编码方式,比如
chunked
- Via:报文经过的中间节点(代理、网关)
- Cache-Control:控制缓存的行为,如
no-cache
。no-cache
表达的是可以缓存,但是每次都需要去服务器确认缓存资源的新鲜度,而不是不缓存
- Connection:浏览器想要优先使用的连接类型,比如
- Request Headers
- 信息性首部
- User-Agent:客户端信息
- Host:服务器的域名
- Refer:提供包含当前请求 URI 的文档的 URL
- From:提供客户端用户的 E-mail 地址
- Accept 首部
- Accept:用户代理期望的
MIME
类型列表,如*/*
- Accept-Charset:用户代理支持的字符集
- Accept-Encoding:用户代理支持的编码方法,如
gzip, deflate
- Accept-Language:用户代理期望的页面语言,如
zh-CN
- Accept:用户代理期望的
- 条件请求首部
- Expect:期待服务端的指定行为
- Range:如果服务器支持范围请求,就请求资源的指定范围
- If-Match:两端资源实体标记比较,相匹配就获取这份资源
- If-None-Match:两端资源实体标记比较,若相同(false)则返回
304
,不相同(true)则返回200
获取资源 - If-Modified-Since:两端资源更新时间比较,服务器确认客户端资源新鲜返回
304
,不新鲜返回200
获取资源
- 安全请求首部
- Cookie:客户端用它向服务器传送一个令牌——非真正的安全首部,但隐含有安全功能
- Authorization:包含了客户端提供给服务器,以便对其自身进行认证的数据
- 代理请求首部
- Proxy-Authorization:代理服务器要求 web 认证信息
- Max-Forwards:限制可被代理及网关转发的次数
- 信息性首部
- Response Headers
- 信息性首部
- Age:资源在代理缓存中存在的时间
- Server:服务器应用程序软件的名称和版本
- 协商首部
- Accept-Ranges:支持资源的某些范围类型,如
bytes
- Vary:服务器查看的其他首部的列表,根据这些首部的内容挑选出最适合的资源版本发送给客户端
- Accept-Ranges:支持资源的某些范围类型,如
- 安全响应首部
- Proxy-Authenticate 向代理服务器发送的验证信息
- Set-Cookie:非真正的安全首部,但隐含有安全功能;可以在客户端设置一个令牌,以便服务器对客户端进行标识
- WWW-Authenticate:服务器对客户端的质询列表
- 信息性首部
- Entity(实体) Headers
- 信息性首部
- Allow:列出了可以对此实体执行的请求方法
- Location:告知客户端重定向到某个 URL
- 内容首部
- Content-Encoding:内容的编码方式
- Content-Language:内容使用的语言
- Content-Length:内容的长度
- Content-Location:返回数据的备用地址
- Content-Range:内容在整个资源中的字节范围
- Content-Type:内容的媒体类型
- 缓存首部
- ETag:与此实体相关的实体标记。标记本质上就是某版本资源的标识符
- Expires:内容的过期时间
- Last-Modified:实体的最后修改时间
- 信息性首部
- 扩展首部:表示用户自定义的首部,通过 X- 前缀来添加
5、缓存
- 强缓存:表示在缓存期间不需要请求,state code 为 200
- Expires:响应头,代表该资源的过期时间, HTTP / 1.0 的产物
- Cache-Control:请求/响应头,缓存控制字段,出现于 HTTP / 1.1,优先级高于 Expires 。属性
Cache-control: max-age=30
表示资源会在 30 秒后过期,需要再次请求
- 协商缓存:缓存过期可以使用协商缓存。协商缓存需要请求,若服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存返回 304。协商缓存需要客户端和服务端共同实现
- Last-Modified 和 If-Modified-Since:
- Last-Modified 表示本地文件最后修改日期
- If-Modified-Since 会将 Last-Modified 的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来
- ETag 和 If-None-Match
- ETag 类似于文件指纹
- If-None-Match 会将当前 ETag 发送给服务器,询问该资源 ETag 是否变动,有变动的话就将新的资源发送回来。并且 ETag 优先级比 Last-Modified 高
- Last-Modified 和 If-Modified-Since:
6、CORS
- 原理:浏览器向服务器发出
Fetch/XHR
请求,服务端使用额外的 HTTP 头部Access-Control-Allow-Origin
就可以告诉浏览器让 web 应用进行跨域资源请求 - 特点:
- CORS 要求服务端设置一些头部字段,最重要的就是
Access-Control-Allow-Origin
- 生产环境中建议用成熟的开源中间件:如前端使用
axios
进行http
传输,后端以koa
作为服务端框架,可使用 CORS 中间件koa2-cors
- CORS 要求服务端设置一些头部字段,最重要的就是
- 跨域请求:
Access-Control-Allow-Origin
为 * 或与 Origin 值相同- 简单请求:不触发预检请求
- 可请求方法:GET, POST 或 HEAD
- 可定义请求头:Accept、Accept-Language、Content-Language、Content-Type( application/x-www-form-urlencoded, multipart/form-data 或 text/plain.)
- 预检请求&正式请求
- 预检请求(浏览器发送 OPTIONS 请求到相同的 url,确认没问题)
- Access-Control-Request-Headers:告知服务器,实际请求将携带自定义请求首部字段
- Access-Control-Request-Method:告知服务器,实际请求将使用相应的方法
- Access-Control-Max-Age:指定预检请求的结果能够被缓存多久,单位是秒
- Access-Control-Allow-Headers、Access-Control-Allow-Methods:表明服务器允许的请求首部字段和请求方法
- Access-Control-Expose-Headers 让服务器把允许浏览器访问的头部字段放入白名单,允许 JavaScript 访问任何其他响应头
- 正式请求:实际请求中发送了对应的头部字段
- 预检请求(浏览器发送 OPTIONS 请求到相同的 url,确认没问题)
- 简单请求:不触发预检请求
//预检请求
axios({
method: "POST",
url: "http://localhost:3000/api/mainRequest",
headers: { "Sec-Fetch-Mode": "CORS" }, // 增加自定义的头部字段
withCredentials: true, // 增加了withCredentials 选项
}).then((data) => {
console.log(data);
});
- 附带身份验证的请求(cookie 不能跨域传递)
- 服务器响应设置
- Access-Control-Allow-Origin 值与 Origin 相同,不能为
*
- Access-Control-Allow-Credentials (凭据)为 true
- Access-Control-Allow-Origin 值与 Origin 相同,不能为
- js 代码请求添加凭据
- XHR:withCredentials: true
- Fetch:credentials: ‘include’
- 服务器响应设置
🗯四、HTTPS
HTTPS 还是通过 HTTP 来传输信息,但 HTTP 报文发送给 TCP 前先将其发送给
TLS
(Transport Layer Security
)传输层安全协议
进行加密。TLS 是个二进制协议,其流量通常是承载在端口 443
1、数字加密
TLS 中使用了两种加密技术,分别为对称加密和非对称加密。
- 对称加密(AES 实现):加密和解密使用相同的密钥。双方需要共享相同的密钥才能通信
- Cipher 加密算法:如
**AES_256_GCM**
- AES_256(Advanced Encryption Standard,高级加密标准):使用长度为 256 位的会话对称加密算法,双方通过 ECDHE 交换参数协商出对称密钥
- GCM(Galois 计数器模式):一种特殊的称为 AEAD 的加密模式
- Cipher 加密算法:如
- 非对称加密(RSA 实现):有公钥和私钥,数据用公钥加密,用私钥解密,私钥只有分发公钥的一方才知道
- Key exchange 密钥协商交换算法:如
**ECDHE_RSA**
- ECDHE(Elliptic Curves Diffie-Hellman Ephemeral)基于椭圆曲线签密方案
D-H
的密钥协商协议,用于协商临时会话密钥 - RSA 算法:证书公钥加密算法,用于对证书数据部分的散列值进行签密、对 ECDHE 交换参数(的 HASH 值)进行签密
- ECDHE(Elliptic Curves Diffie-Hellman Ephemeral)基于椭圆曲线签密方案
- Key exchange group,如
**X25519**
- X25519:椭圆曲线密钥交换算法,Curve25519 是目前最高水平的 Diffie-Hellman 函数,适用于广泛的场景
- Key exchange 密钥协商交换算法:如
- 可逆加密:经过加密过后的信息可以通过对应的密钥反向解析还原信息内容
- 对称加密算法:AES、DES、3DES、Blowfish、IDEA、RC4、RC5、RC6
- 非对称加密算法:RSA、DSA(数字签名用)、ECC(移动设备用)、Diffie-Hellman、El Gamal
- Base64 编码算法:常用于把二进制数据编码为可写的字符形式的数据,适合在 HTTP,MIME 协议下的网络快速传输数据(URL、Cookie、网页中传输少量二进制数据),可对 img 图像编码用于传输
- 不可逆(单向)哈希算法:加密后的信息是原信息的“散列”或“消息摘要”,无法反向解析还原信息内容。
- MD5 (Message-Digest Algorithm 5) 即消息摘要算法
- SHA(Secure Hash Algorithm)即安全散列算法:如
**SHA-256**
- 基于有密钥的加密散列函数,用于创建消息摘要/指纹
- 使用安全散列算法 2(SHA-2)生成 256 字节的摘要,确保消息的完整性(没有被篡改)
- 通常用于 RSA 私钥签名,RSA 公钥验签
- HMAC(Hash-based Message Authentication Code)即基于哈希的消息认证码
- 以一个密钥和一个消息为输入,生成一个消息摘要作为输出。有效防止一些类似 MD5 的彩虹表等攻击
- Bcrypt/PBKDF2:相对运算比较慢的算法,越慢的算法越安全。经过
salt
和cost
的处理,使其受rainbow
攻击破解的概率大大降低,同时破解的难度也提升不少
2、TLS 握手协议
Handshake 协议:负责协商使用的 TLS 版本、加密算法、哈希算法、密钥材料等,对服务器、客户端(可选)进行身份认证,最后对整个握手阶段信息进行完整性校验以防范中间人攻击,是整个 TLS 协议的核心。TLS 1.2 协议需要两次往返( 2-RTT )才能完成握手,然后才能发送请求。
TLS 1.3 协议不再支持静态的RSA
密钥交换(不是前向安全算法),引入了新的密钥协商机制 —PSK
。首次建立连接只需要 1-RTT
Client
发送Client Hello
报文给Server
,其中密钥协商扩展包含一个随机数 Random1、TLS 协议版本、支持的加密套件列表(按优先级排列)Server
发送Server Hello
报文给Client
,其中密钥协商扩展包含一个新的随机数 Random2、TLS 协议版本、经过选择后的一个加密套件Server
发送Certificate
报文给Client
,传递自己的证书信息,包含服务器 X.509 证书链。客户端验证通过后取出证书中的公钥Server
发送Server Key Exchange
报文给Client
,密钥交换选择 DH 算法,报文包含密钥交换所需的服务端 DH 参数Server
发送Server Hello Done
报文给Client
,表明服务端到客户端信道的握手阶段结束,理论上不得再由该信道发送任何握手报文Client
发送Client Key Exchange
报文给Server
,密钥交换选择 DH 算法,报文包含客户端 DH 参数。双方都根据 DH 算法计算出相同的预主密钥 Premaster secret,然后再结合Random1、Random2 使用Client
发送Change Cipher Spec
报文给Server
,表明已经生成主密钥 session key,在随后的传输过程都使用这个主密钥对消息进行对称加密Client
发送Finished
报文给Server
,这条消息是经过加密的,因此在 Wireshark 中显示的是 Encrypted Handshake Message。如果服务器能解密出报文内容,则说明双方生成的主密钥是一致的Server
发送New Session Ticket
报文给Client
,而这个 Session Ticket 只有服务器才能解密,客户端把它保存下来,在以后的 TLS 重新握手过程中带上它进行快速会话恢复,减少往返延迟Server
发送Change Cipher Spec
报文给Client
,同样表明已经生成主密钥 session key,在随后的传输过程都使用这个主密钥对消息进行对称加密Server
发送Finished
报文给Client
,如果客户端能解密出报文内容,则说明双方生成的主密钥是一致的。至此,完成所有握手协商
🏻五、HTTP 2.0
队头阻塞(Head of line blocking):导致在达到最大请求数量时,剩余的资源需要等待其他资源请求完成后才能发起请求
1、二进制传输
在之前的 HTTP 版本中,我们是通过文本的方式传输数据。在 HTTP 2.0 中引入了新的编码机制,所有传输的数据都会被分割,并采用二进制格式编码。
2、多路复用
帧:代表着最小的数据单位,每个帧会标识出该帧属于哪个流;
流:多个帧组成的数据流
多路复用:一个 TCP 连接中可存在多条流,即可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。以避免 HTTP 旧版本的队头阻塞问题,极大提高传输性能
3、Header 压缩
HTTP 2.0 中,使用了HPACK
压缩格式对传输的 header 进行编码,减少了 header 的大小。并在两端维护了索引表,用于记录出现过的 header ,后面在传输过程中就可以传输已经记录过的 header 的键名,对端收到数据后就可以通过键名找到对应的值
4、服务端 Push
DNS Prefetch(
DNS
预获取):让具有此属性的域名不需要用户点击链接就在后台解析,而域名解析和内容载入是串行的网络操作,所以该方式能减少用户的等待时间,提升用户体验
HTTP 2.0 中,服务端可以在客户端某个请求后,主动推送其他资源。提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用prefetch
5、QUIC
QUIC(Quick UDP Internet Connection)快速 UDP 互联网连接:一种基于UDP
协议的实验性的传输层协议,它在两个端点之间创建连接,且支持多路复用。
- 支持多路复用
- 实现了自己的加密协议,通过类似 TCP 的 TFO 机制可以实现 0-RTT
- 支持重传和纠错机制(向前恢复),在只丢失一个包的情况下不需要重传,使用纠错机制恢复丢失的包
🐣六、TCP
TCP:提供一种面向连接的、可靠的字节流服务。保证数据通信的完整性和可靠性,防止丢包。TCP 建立连接需要三次握手,断开连接需四次握手。效率比不上 UDP 协议,但具有重发包,顺序控制等机制
1、特点
- 连接识别:源 IP 地址、源端口号、目的 IP 地址、目的端口号
- 可靠性高:TCP 为 HTTP 提供了一条可靠的比特传输管道
- 数据包校验、对失序数据包重排序
- 丢弃重复数据、自动重传、超时重发、流量控制
- 分段、分组传送:TCP 报文被打包为报文段,再通过 IP 分组( IP 数据报)封装来发送的。每个 IP 分组中都包括: IP 分组首部、 TCP 段首部、 TCP 数据块
2、TCP 段
- 序列号(Sequence number):对数据包进行标记,保证传输的报文都是有序的
- 确认号(Acknowledgement Number):期望收到对方下一个报文段的序号值,表示上一序号的数据已收到
- 窗口大小(Window Size):表示还能接收多少字节的数据,用于流量控制
- 标识符
- URG=1:该字段表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针有效
- ACK=1:该字段表示确认号字段有效。此外,TCP 还规定在连接建立后传送的所有报文段都必须把 ACK 置一
- PSH=1:该字段表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交
- RST=1:复位报文段。该字段表示当前 TCP 连接出现严重问题,可能需要重新建立 TCP 连接,也可以用于拒绝非法的报文段和拒绝连接请求
- SYN=1:同步报文段。当 SYN=1,ACK=0 时,表示一个连接请求报文。当 SYN=1,ACK=1 时,表示一个同意建立连接的应答报文
- FIN=1:结束报文段。该字段表示此报文段是一个释放连接的请求报文
3、建立连接三次握手(两端交换 ISN,证明两端收发能力 OK)
- 客户端发送
SYN
报文,指明客户端初始化序列号x = ISN(c)
- 服务端发送
SYN+ACK
报文,指明服务端初始化序列号y = ISN(s)
,确认号ACK = x+1 = ISN(c)+1
- 客户端发送
ACK
报文,指明确认号ACK = y+1 = ISN(s)+1
- 第三次握手中可以携带数据:
- 服务器在第二个握手报文中嵌入不透明 Cookie(
Opaque Cookie
),第三个握手报文中携带这个不透明 Cookie(Opaque Cookie
)的为真实IP
- 服务器在第二个握手报文中嵌入不透明 Cookie(
- 为什么还需要第三次握手?
- 防止失效的连接请求报文段被服务端接收,产生错误
- 第三次握手 ACK 丢失会发生什么?
- 超时重传 SYN 包,一般会重试五次,在建立连接中可能会遇到 SYN FLOOD 攻击,可选择调低重试次数或在不能处理的情况下拒绝请求
- 第三次握手中可以携带数据:
4、断开连接四次挥手
4.1 断开连接
- 服务器向客户端发送 Alert 报文,类型为 Close Notify,通知客户端不再发送数据,即将关闭连接,同样,这条报文也是经过加密处理的。
- 服务器调用 close 函数主动关闭连接,发送带 FIN 标志位的分组,序列号为 m
- 客户端确认收到该分组,发送带 ACK 标志位的分组,确认号为 m+1
- 客户端发送完所有数据后,向服务器发送带有 FIN 标志位的分组,序列号为 n
- 服务器确认收到该分组,发送带 ACK 标志位的分组,序列号为 n+1。客户端收到确认分组后,立即进入 CLOSED 状态;同时,服务器等待 2 个 MSL(Maximum Segment Lifetime,最大报文生存时间) 的时间后,进入 CLOSED 状态
4.2 四次挥手
第二次挥手后, 客户端不再向服务端请求任何数据, 但服务端可能还正在给客户端发送数据,此时服务端会等待数据传输完毕后再发送关闭请求
- 为什么 Client 要进入 TIME-WAIT 状态等待 2MSL 时间后才进入 CLOSED 状态?
- 可靠实现 TCP 全双工连接的终止:被动关闭的一方可能收不到主动关闭一方最后发送的 ACK,因此一定是主动关闭的一方需要 TIME_WAIT,以便重传最后那个 ACK
- 保证 Server 能收到 Client 的确认应答
- 直接进入 CLOSED 状态时,如果确认应答因为网络问题一直没有到达,会造成 server 不能正常关闭
- 2MSL 时间能保证当前连接的所有分组都被丢弃,建立新连接时就不可能接受到前一个连接的重复分组
5、ARQ 协议
ARQ(Automatic Repeat Request):即自动重传请求。当请求失败时它会自动重传,直到请求被正确接收为止,保证了数据的正确送达。ARQ 协议包含停止等待 ARQ 和连续 ARQ
- 停止等待 ARQ:只要 A 向 B 发送一段报文,都要停止发送并启动一个定时器,等待对端
ACK
,在定时器时间内接收到对端应答就取消定时器并发送下一段报文 - 连续 ARQ:发送端拥有一个发送窗口,可以在没有收到应答的情况下持续发送窗口内的数据。通过累计确认,可以在收到多个报文以后统一回复一个应答报文
6、滑动窗口(Sliding window)
- 作用:实现了流量控制,控制发送方发送速率,保证接收方来得及接收
- 发送端窗口
- 组成:已发送但未收到应答的数据、可以发送但未发送的数据
- 大小:不断变化的。接收方会把当前接收窗口的剩余大小写入应答报文,发送端收到应答后根据该值和当前网络拥塞情况设置发送窗口的大小
- 滑动:当发送端接收到应答报文后,会随之将窗口进行滑动
- zero 窗口
- 发送报文的过程中,可能会遇到对端出现零窗口的情况,发送端会停止发送数据,并启动
persistent timer
- 定时器会定时发送请求给对端,让对端告知窗口大小。重试超过一定次数后,可能会中断 TCP 链接
- 发送报文的过程中,可能会遇到对端出现零窗口的情况,发送端会停止发送数据,并启动
7、拥塞控制
作用于网络,防止过多的数据拥塞网络,避免出现网络负载过大
- 慢开始算法:传输开始时将发送窗口慢慢指数级扩大
- 拥塞避免算法:每过一个 RTT(round-trip time,往返时间) 窗口大小只加一,避免指数级增长导致网络拥塞,慢慢将大小调整到最佳值
- 快速重传+快速恢复算法(fast retransmit and recovery,FRR)
⛲七、UDP
- 面向报文:UDP 只是报文的搬运工,不会对报文进行任何拆分和拼接操作。
- 不可靠性:无连接的;尽最大努力交付,即不保证可靠交付;没有拥塞控制
- 高效:头部开销小,只有八字节
- 传输方式:支持一对一、一对多、多对一和多对多的交互通信
🌷八、IP
IP 地址:指明节点被分配到的网络地址,用于区分两台主机是否同属一个网络
MAC 地址:指网卡所属的固定地址。采用十六进制标识,共6个字节, 前三个字节是厂商编号,后三个字节是网卡流水号,例如 4C-0F-6E-12-D2-19
- IPV4 地址:32位的地址,常采用4个十进制数字表示。例如C类地址192.168.24.1
- 前面部分代表网络地址。若两个IP地址在同一子网内,则网络地址一定相同
- 后面部分表示该主机在局域网中的地址
- IP 地址可以和 MAC 地址进行配对,IP 间的通信依赖 MAC 地址
- IP 地址可变换,但 MAC 地址基本上不会更改
- ARP 地址解析协议:根据IP地址获取MAC地址的一个网络层协议
🗻 九、从输入 URL 到页面加载完成
1、DNS 解析
首先做DNS查询
,智能 DNS 解析会提供访问速度最快的 IP 地址回来。
2、HTTP 请求、响应
除了在浏览器直接发起 HTTP 之外,你也可以用命令行 telnet 来与服务器指定端口建立 TCP 连接,按照协议规定的格式,来发送请求头和请求实体。另外,如果想查看详细具体的封包内容,可以使用网络封包分析工具 Wireshark 或命令行 tcpdump,来捕获某一块网卡上的数据包。
DNS 解析拿到服务器 IP 地址后,浏览器通过系统调用 Socket 接口与服务器 443 端口进行通信,整个过程含建立连接、发送 HTTP 请求、返回 HTTP 响应、维持连接。
2.1 建立连接
- TCP 握手:客户端发送
SYN
报文,指明客户端初始化序列号x = ISN(c)
; 服务端发送SYN+ACK
报文,指明服务端初始化序列号y = ISN(s)
,确认号ACK = x+1 = ISN(c)+1
; 客户端发送ACK
报文,指明确认号ACK = y+1 = ISN(s)+1
。连接建立 - TLS握手:两端交换随机数、DH算法参数、加密套件等生成主密钥,对消息进行对称加密
2.2 发送 HTTP 请求、返回 HTTP 响应
建立起安全的加密信道后,浏览器开始发送 HTTP 请求,一个请求报文由请求行、请求头、空行、实体(Get 请求没有)组成。经过负责负载均衡的服务器接受并处理完请求,返回 HTTP 响应,一个响应报文由响应行、响应头、空行、实体组成。
2.3 维持连接
HTTP/1.1 中 Connection: keep-alive 默认启用,表示持久连接,以便处理不久后到来的新请求,无需重新建立连接而增加慢启动开销,提高网络的吞吐能力
- Nginx 中持久连接超时时间默认值为 75 秒,期间无请求则断开与客户端的连接
- 浏览器每隔 45 秒会向服务器发送 TCP keep-alive 探测包,来判断 TCP 连接状况,如果没有收到 ACK 应答,则主动断开与服务器的连接
3、浏览器解析文件、渲染
- 浏览器判断状态码:200 就继续解析,400 或 500 就报错,300 会进行重定向,重定向计数器可避免过多次的重定向,超过次数会报错
- 根据文件格式解析:如果 gzip 格式会先解压,然后通过文件的编码格式去解码,解码成功后渲染;如果为 html 文件则直接开始渲染
- 浏览器渲染:先会根据 HTML 构建 DOM 树,有 CSS 的话会去构建 CSSOM 树。如果遇到 script 标签的话,会判断是否存在 async 或者 defer ,前者会并行进行下载并执行 JS,后者会先下载文件,然后等待 HTML 解析完成后顺序执行,如果以上都没有,就会阻塞住渲染流程直到 JS 执行完毕。遇到文件下载的会去下载文件,这里如果使用 HTTP 2.0 协议的话会极大的提高多图的下载效率
- 初始的HTML被完全加载和解析后触发
DOMContentLoaded
事件 - CSSOM 树和 DOM 树构建完成后会开始生成 Render 树,确定页面元素的布局、样式等
- 生成 Render 树过程中,调用 GPU 绘制并合成图层,将内容显示在屏幕上
- 初始的HTML被完全加载和解析后触发
十、参考资料
1、《当你在浏览器中输入 google.com 并且按下回车之后发生了什么?》
2、《解密HTTP/2与HTTP/3 的新特性》
3、《what-happens-when》
4、《what-happen》