简单来讲,用户打开浏览器,浏览器根据前端框架(包括vue,react等框架)执行js代码,渲染前端界面。用户在各式的界面里,点击按钮,浏览器捕捉点击事件,执行绑定的js代码。
前端侧示例
button.addEventListener('click', () => {
fetch('/api/order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ orderId: 1001 })
});
});
用户点击按钮后,浏览器会触发 click 事件,执行这段回调函数。fetch 会向 /api/order 发起一个 POST 请求
请求体 { "orderId": 1001 }
q:
1.浏览器是如何渲染界面的
2.浏览器是如何捕捉到点击事件的
浏览器侧
浏览器捕捉到点击事件,首先要知道自己要将这个请求发给谁
/api/order 是一个根相对路径 (以 / 开头),默认情况下,浏览器会以当前页面的 origin(协议 + 域名 + 端口,不含路径) 为基准,以www.example.com为例,和前面的/api/order补全...
此时浏览器就可以知道
协议(后端应该以什么方式接收):https
发送的位置:
域名(前端应该发送请求到什么地方的服务器):www.example.com
端口(前端应该发送请求到服务器的哪个端口):默认 443
路径(前端应该发送请求到端口下的哪个位置):/api/order
q:
1.为什么发送的位置有3个自由度,不能像协议一样只有1个自由度
2.域名,端口,路径各自的作用是什么。
先解决域名的作用是什么?
域名是作为人类标识,便于人类查看的
一个域名对应一组ip集合(单机架构或者负载均衡,高可用,就近访问等)
比如www.example.com 对应的是203.0.113.45
浏览器就可以根据域名来获取对应的ip地址
q:
1.浏览器是如何获取根据域名来获取ip地址的。(DNS缓存)
拿到ip地址之后,浏览器(前端)开始和服务器(后端)建立连接
建立tcp连接,http默认80,https默认443端口
端口在这里就确定了
然后进行 TCP 三次握手:
- 客户端发送 SYN,请求建立连接;
- 服务器回复 SYN + ACK,表示同意连接;
- 客户端发送 ACK ,连接正式建立。
建立完传输通道
q:
1.tcp三次握手是如何实现的,为什么三次握手之后可以建立好传输通道
如果是 HTTPS,再进行 TLS 握手
- 浏览器发送支持的 TLS 版本和加密套件;
- 服务器返回选定的加密套件和数字证书;
- 浏览器验证证书:是否可信、域名是否匹配、是否过期;
- 双方协商并生成会话密钥;
- 后续通信都使用这个密钥加密。
建立完加密通道
q:
1.TLS握手为什么可以建立加密通道
发送http请求
浏览器会构造 HTTP 请求报文:
- 请求方法:GET、POST 等;
- URL 路径:比如 /api/order;
- 请求头:Host、User-Agent、Cookie、Accept 等;
- 请求体:POST 请求时携带的数据。
服务器处理并返回响应
服务器返回响应
- 状态码:200 成功、301 重定向、404 未找到、500 服务器错误等;
- 响应头:Content-Type、Cache-Control 等;
- 响应体 :HTML、JSON、图片、文件等。
q:
1.服务器是怎么返回给谁的
2.服务器怎么知道多久返回
浏览器如何处理响应
浏览器会根据请求类型分别处理:
- 如果是文档请求 ,比如用户打开页面时请求
/或/index.html,浏览器会解析 HTML 构建 DOM 树,加载并解析 CSS 构建 CSSOM 树,合并生成渲染树,再计算布局并绘制页面。 - 如果是接口请求 ,比如
fetch('/api/order')返回的 JSON,浏览器不会重新渲染整个页面,而是把响应交给 JavaScript。前端代码通过res.json()解析数据后,再由 Vue、React 等框架更新对应的视图。
关闭tcp连接
数据传输完成后,如果连接不需要复用,就会进行 TCP 四次挥手:
- 客户端发送 FIN,表示"我这边数据发完了";
- 服务器回复 ACK,表示"收到";
- 服务器发送 FIN,表示"我这边也发完了";
- 客户端回复 ACK ,表示"好的,连接可以关闭了"。
客户端通常还会等待 2MSL 时间,确保最后一个 ACK 到达,并让网络中的旧报文消失,然后才彻底关闭连接。
q:
1.tcp四次挥手是如何实现的,为什么四次挥手之后可以关闭传输通道
tips:以上提出的问题会在后续文章中解答