当前位置: 首页 > article >正文

【linux网络编程】浏览网页时客户端与服务器之间数据交互的完整过程

浏览网页时,客户端与服务器之间数据交互的完整过程

当你在浏览器中输入一个网址(例如 http://www.example.com),然后按下回车,计算机(客户端)与服务器之间会进行一系列复杂的交互,最终将网页呈现出来。

整个过程可以分为 DNS解析、TCP连接、HTTP请求、服务器处理、HTTP响应、渲染网页 这几个主要步骤,下面详细讲解每个步骤的工作流程。


1. 解析URL(输入网址)

用户在浏览器地址栏输入 http://www.example.com,浏览器会解析该 URL(统一资源定位符)

  • http:// —— 指定使用 HTTP协议(或 https:// 表示使用 HTTPS)。
  • www.example.com —— 这是服务器的域名,需要解析成 IP地址
  • /index.html(或 /)—— 这是请求的资源路径,默认为 index.html

2. DNS解析(域名解析)

由于计算机只识别 IP地址,而不是人类易读的域名,因此浏览器需要先将 www.example.com 解析为对应的 IP地址

DNS解析过程

  1. 浏览器缓存:浏览器首先检查本地缓存,看是否已经解析过 www.example.com
  2. 操作系统缓存:如果浏览器缓存没有命中,则查询操作系统的 DNS缓存/etc/hostsWindows hosts 文件)。
  3. 本地DNS服务器(ISP提供的):如果本地缓存没有找到,操作系统会向本地DNS服务器(通常是ISP提供的)发送查询请求。
  4. 根DNS服务器:本地DNS服务器如果没有缓存该域名,会向 根DNS服务器 请求 .com 顶级域名服务器地址。
  5. 顶级域名服务器(TLD服务器):顶级域名服务器(TLD,如 .com 的DNS服务器)会告诉本地DNS服务器 example.com 的权威DNS服务器。
  6. 权威DNS服务器:权威DNS服务器返回 www.example.comIP地址(如 192.168.1.10)。
  7. 返回IP地址:本地DNS服务器将解析结果缓存,并返回给操作系统,最终浏览器拿到服务器的 IP地址

3. 建立TCP连接(三次握手)

在获取到服务器的 IP地址 后,浏览器需要和服务器建立 TCP连接。此时客户端会向服务器的 80号端口(HTTP)443号端口(HTTPS) 发起TCP连接请求。

TCP三次握手

TCP协议使用 三次握手 来保证可靠连接:

  1. 客户端 → 服务器:SYN
    • 客户端发送 SYN(同步)包,告诉服务器 “我想要建立连接”,并带上一个 初始序列号(seq=x)
  2. 服务器 → 客户端:SYN-ACK
    • 服务器收到 SYN 后,回复 SYN-ACK(同步确认)包,表示同意连接,并带上自己的初始序列号(seq=y,ack=x+1)。
  3. 客户端 → 服务器:ACK
    • 客户端收到 SYN-ACK 后,发送 ACK(确认)包,表示连接已建立(ack=y+1)。
    • 至此,TCP连接建立完成,进入数据传输阶段。

4. 发送HTTP请求

TCP连接建立后,浏览器向服务器发送 HTTP请求 获取网页内容。

HTTP请求结构

请求由 请求行、请求头、请求体 组成,示例如下:

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64)
Accept: text/html
Connection: keep-alive
HTTP请求解析
  • GET /index.html HTTP/1.1 —— 请求方法是 GET,请求 index.html 页面,使用 HTTP 1.1 协议。
  • Host: www.example.com —— 目标服务器的 域名
  • User-Agent: Mozilla/5.0 —— 浏览器信息(用于适配不同设备)。
  • Accept: text/html —— 期望返回 HTML格式 数据。
  • Connection: keep-alive —— 维持 TCP长连接(减少重复建立连接的开销)。

5. 服务器处理请求

服务器收到 HTTP请求 后,进行以下操作:

  1. 解析请求,确认访问的资源(如 /index.html)。
  2. 检查权限,确认客户端是否有访问权限(如 401 Unauthorized)。
  3. 读取文件,如 index.html 或调用后端代码(PHP/Python/Java) 生成动态内容。
  4. 准备HTTP响应,将网页数据返回给客户端。

6. 服务器返回HTTP响应

服务器将网页数据封装在 HTTP响应 中返回:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Connection: keep-alive

<html>
  <head><title>Example</title></head>
  <body><h1>Welcome!</h1></body>
</html>
HTTP响应解析
  • HTTP/1.1 200 OK —— 表示请求成功,状态码 200
  • Content-Type: text/html —— 响应内容为 HTML 格式。
  • Content-Length: 1024 —— 响应体大小(1024字节)。
  • Connection: keep-alive —— 维持 TCP连接,避免每次都重新建立连接。

7. 浏览器解析与渲染网页

浏览器收到服务器返回的 HTML 代码后,会执行以下步骤:

  1. 解析HTML,构建 DOM树(文档对象模型)。
  2. 解析CSS,构建 CSSOM树(CSS对象模型)。
  3. 执行JavaScript,可能会修改HTML或CSS。
  4. 合成Render Tree,结合 DOM树 + CSSOM树 生成渲染树
  5. 布局(Layout),计算每个元素的位置和大小。
  6. 绘制(Painting),最终将页面渲染到屏幕。

8. 持续交互(AJAX、WebSocket)

  • AJAX(异步请求):浏览器可以使用 XMLHttpRequestfetch 进行异步数据请求(如动态加载新闻)。
  • WebSocket:用于长连接通信,实现实时聊天、股票行情推送等。

9. 断开连接(四次挥手)

当网页加载完成,客户端和服务器的连接可能会被关闭(如果 Connection: keep-alive 允许,连接会保持一段时间)。

TCP四次挥手(断开连接)

  1. 客户端 → 服务器:FIN(请求关闭连接)
  2. 服务器 → 客户端:ACK(确认关闭请求)
  3. 服务器 → 客户端:FIN(服务器主动关闭)
  4. 客户端 → 服务器:ACK(确认关闭)

至此,TCP连接完全关闭。

浏览网页时,客户端与服务器之间数据交互的完整过程

当你在浏览器中输入一个网址(例如 http://www.example.com),然后按下回车,计算机(客户端)与服务器之间会进行一系列复杂的交互,最终将网页呈现出来。

整个过程可以分为 DNS解析、TCP连接、HTTP请求、服务器处理、HTTP响应、渲染网页 这几个主要步骤,下面详细讲解每个步骤的工作流程。


1. 解析URL(输入网址)

用户在浏览器地址栏输入 http://www.example.com,浏览器会解析该 URL(统一资源定位符)

  • http:// —— 指定使用 HTTP协议(或 https:// 表示使用 HTTPS)。
  • www.example.com —— 这是服务器的域名,需要解析成 IP地址
  • /index.html(或 /)—— 这是请求的资源路径,默认为 index.html

2. DNS解析(域名解析)

由于计算机只识别 IP地址,而不是人类易读的域名,因此浏览器需要先将 www.example.com 解析为对应的 IP地址

DNS解析过程

  1. 浏览器缓存:浏览器首先检查本地缓存,看是否已经解析过 www.example.com
  2. 操作系统缓存:如果浏览器缓存没有命中,则查询操作系统的 DNS缓存/etc/hostsWindows hosts 文件)。
  3. 本地DNS服务器(ISP提供的):如果本地缓存没有找到,操作系统会向本地DNS服务器(通常是ISP提供的)发送查询请求。
  4. 根DNS服务器:本地DNS服务器如果没有缓存该域名,会向 根DNS服务器 请求 .com 顶级域名服务器地址。
  5. 顶级域名服务器(TLD服务器):顶级域名服务器(TLD,如 .com 的DNS服务器)会告诉本地DNS服务器 example.com 的权威DNS服务器。
  6. 权威DNS服务器:权威DNS服务器返回 www.example.comIP地址(如 192.168.1.10)。
  7. 返回IP地址:本地DNS服务器将解析结果缓存,并返回给操作系统,最终浏览器拿到服务器的 IP地址

3. 建立TCP连接(三次握手)

在获取到服务器的 IP地址 后,浏览器需要和服务器建立 TCP连接。此时客户端会向服务器的 80号端口(HTTP)443号端口(HTTPS) 发起TCP连接请求。

TCP三次握手

TCP协议使用 三次握手 来保证可靠连接:

  1. 客户端 → 服务器:SYN
    • 客户端发送 SYN(同步)包,告诉服务器 “我想要建立连接”,并带上一个 初始序列号(seq=x)
  2. 服务器 → 客户端:SYN-ACK
    • 服务器收到 SYN 后,回复 SYN-ACK(同步确认)包,表示同意连接,并带上自己的初始序列号(seq=y,ack=x+1)。
  3. 客户端 → 服务器:ACK
    • 客户端收到 SYN-ACK 后,发送 ACK(确认)包,表示连接已建立(ack=y+1)。
    • 至此,TCP连接建立完成,进入数据传输阶段。

4. 发送HTTP请求

TCP连接建立后,浏览器向服务器发送 HTTP请求 获取网页内容。

HTTP请求结构

请求由 请求行、请求头、请求体 组成,示例如下:

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64)
Accept: text/html
Connection: keep-alive
HTTP请求解析
  • GET /index.html HTTP/1.1 —— 请求方法是 GET,请求 index.html 页面,使用 HTTP 1.1 协议。
  • Host: www.example.com —— 目标服务器的 域名
  • User-Agent: Mozilla/5.0 —— 浏览器信息(用于适配不同设备)。
  • Accept: text/html —— 期望返回 HTML格式 数据。
  • Connection: keep-alive —— 维持 TCP长连接(减少重复建立连接的开销)。

5. 服务器处理请求

服务器收到 HTTP请求 后,进行以下操作:

  1. 解析请求,确认访问的资源(如 /index.html)。
  2. 检查权限,确认客户端是否有访问权限(如 401 Unauthorized)。
  3. 读取文件,如 index.html 或调用后端代码(PHP/Python/Java) 生成动态内容。
  4. 准备HTTP响应,将网页数据返回给客户端。

6. 服务器返回HTTP响应

服务器将网页数据封装在 HTTP响应 中返回:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Connection: keep-alive

<html>
  <head><title>Example</title></head>
  <body><h1>Welcome!</h1></body>
</html>
HTTP响应解析
  • HTTP/1.1 200 OK —— 表示请求成功,状态码 200
  • Content-Type: text/html —— 响应内容为 HTML 格式。
  • Content-Length: 1024 —— 响应体大小(1024字节)。
  • Connection: keep-alive —— 维持 TCP连接,避免每次都重新建立连接。

7. 浏览器解析与渲染网页

浏览器收到服务器返回的 HTML 代码后,会执行以下步骤:

  1. 解析HTML,构建 DOM树(文档对象模型)。
  2. 解析CSS,构建 CSSOM树(CSS对象模型)。
  3. 执行JavaScript,可能会修改HTML或CSS。
  4. 合成Render Tree,结合 DOM树 + CSSOM树 生成渲染树
  5. 布局(Layout),计算每个元素的位置和大小。
  6. 绘制(Painting),最终将页面渲染到屏幕。

8. 持续交互(AJAX、WebSocket)

  • AJAX(异步请求):浏览器可以使用 XMLHttpRequestfetch 进行异步数据请求(如动态加载新闻)。
  • WebSocket:用于长连接通信,实现实时聊天、股票行情推送等。

9. 断开连接(四次挥手)

当网页加载完成,客户端和服务器的连接可能会被关闭(如果 Connection: keep-alive 允许,连接会保持一段时间)。

TCP四次挥手(断开连接)

  1. 客户端 → 服务器:FIN(请求关闭连接)
  2. 服务器 → 客户端:ACK(确认关闭请求)
  3. 服务器 → 客户端:FIN(服务器主动关闭)
  4. 客户端 → 服务器:ACK(确认关闭)

至此,TCP连接完全关闭。


总结

  1. DNS解析www.example.com 转换为 IP 地址。
  2. 建立TCP连接(三次握手)。
  3. 发送HTTP请求 获取网页资源。
  4. 服务器处理请求 并返回HTTP响应
  5. 浏览器解析HTML/CSS/JS 并渲染页面。
  6. 可能存在AJAX/WebSocket等交互
  7. 关闭TCP连接(四次挥手)。

这个过程保证了网页的正确加载,并提供了动态交互能力。

总结

  1. DNS解析www.example.com 转换为 IP 地址。
  2. 建立TCP连接(三次握手)。
  3. 发送HTTP请求 获取网页资源。
  4. 服务器处理请求 并返回HTTP响应
  5. 浏览器解析HTML/CSS/JS 并渲染页面。
  6. 可能存在AJAX/WebSocket等交互
  7. 关闭TCP连接(四次挥手)。

TCP 四次挥手(断开连接)详细解析

TCP 连接在数据传输完成后,需要 断开连接,这个过程不像建立连接(三次握手)那样简单,而是需要 四次挥手 来确保双方都可以安全地断开。


1. 为什么需要四次挥手?

TCP 是一个全双工(Full-Duplex) 协议,意味着通信的双方(客户端和服务器)都可以同时发送和接收数据。

  • 当一方(如客户端)不再需要发送数据时,需要通知对方“我不发了”,但仍然可以接收数据。
  • 另一方(如服务器)可能还有数据要发,所以它不能立即断开,而是需要等数据传输完成后,再关闭连接。

因此,TCP 需要四次挥手来保证数据的完整性,避免未传输完的数据丢失。


2. TCP 四次挥手的完整过程

四次挥手的每一步都涉及TCP 报文,其中包含 FIN(Finish) 和 ACK(Acknowledge) 标志位。

📌 第一步:客户端发送 FIN(主动关闭)

客户端(想要关闭连接的一方)发送 FIN(Finish) 报文,表示:

“我不再发送数据了,但我还能接收你的数据。”

📌 客户端发送的 TCP 报文

标志位:FIN=1, ACK=0
序列号(SEQ)= X

📌 服务器的状态变化

  • 服务器收到 FIN 后,进入 CLOSE_WAIT 状态,表示:

    “我知道你不发数据了,但我可能还有数据要发。”

  • 服务器 仍然可以继续发送数据 给客户端。

📌 第二步:服务器发送 ACK(确认 FIN)

服务器 回复一个 ACK(Acknowledge) 报文,表示:

“我收到了你的关闭请求,但我还没准备好关闭连接。”

📌 服务器发送的 TCP 报文

标志位:FIN=0, ACK=1
确认号(ACK)= X+1

📌 客户端的状态变化

  • 客户端收到 ACK 后,进入 FIN_WAIT_2 状态,等待服务器最终的关闭请求。

📌 第三步:服务器发送 FIN(服务器准备关闭)

服务器 处理完剩余的数据后,也发送 FIN(Finish) 报文,表示:

“我也不发数据了,现在可以正式关闭连接。”

📌 服务器发送的 TCP 报文

标志位:FIN=1, ACK=0
序列号(SEQ)= Y

📌 客户端的状态变化

  • 客户端收到 FIN 后,进入 TIME_WAIT 状态,并准备发送最后的 ACK 进行确认。

📌 第四步:客户端发送 ACK(确认关闭)

客户端 发送最终的 ACK(Acknowledge) 报文,表示:

“我收到了你的关闭请求,连接正式断开。”

📌 客户端发送的 TCP 报文

标志位:FIN=0, ACK=1
确认号(ACK)= Y+1

📌 服务器的状态变化

  • 服务器收到 ACK 后,直接关闭连接,进入 CLOSED 状态。

📌 客户端的状态变化

  • 客户端进入 TIME_WAIT 状态,并等待一段时间(默认 2 * MSL(最大报文生存时间)),以确保服务器收到 ACK 后正确关闭。

3. 为什么客户端要等待 TIME_WAIT?

在第四步完成后,客户端不会立即关闭,而是进入 TIME_WAIT 状态,通常会等待 2 * MSL(最大报文生存时间,通常是 30s~120s)。

原因

  1. 防止服务器没有收到 ACK

    • 如果 ACK 丢失,服务器会重发 FIN,客户端可以在 TIME_WAIT 期间再次发送 ACK,避免服务器错误地保持连接。
  2. 确保旧的 TCP 连接数据包不会影响新连接

    • 如果立即关闭,可能会导致新的连接收到旧连接的延迟数据包,造成数据混乱。

TIME_WAIT 的影响

  • 由于客户端需要等待一段时间,如果并发连接过多,可能会导致大量端口占用。
  • 解决方案:
    • 优化端口复用(如 SO_REUSEADDR 选项)。
    • 减少 TIME_WAIT 时间(如 Linux 内核参数 net.ipv4.tcp_fin_timeout)。

4. 服务器为何不需要 TIME_WAIT?

一般情况下,TIME_WAIT 由主动关闭连接的一方负责(通常是客户端)。

  • 服务器通常是被动方,等待客户端关闭,因此它直接进入 CLOSED 状态,不需要等待。
  • 如果服务器也是主动关闭方(如 kill 进程),则它也会进入 TIME_WAIT

5. 总结

步骤发送方报文内容说明
1客户端 → 服务器FIN=1客户端请求关闭连接,不再发送数据,但仍可接收数据
2服务器 → 客户端ACK=1服务器确认关闭请求,但仍可能发送剩余数据
3服务器 → 客户端FIN=1服务器处理完数据,正式关闭
4客户端 → 服务器ACK=1客户端确认,进入 TIME_WAIT,确保服务器收到后断开

🔹 关键点

  1. 客户端先发送 FIN,请求关闭连接。
  2. 服务器先回复 ACK,但仍可能继续发送数据。
  3. 服务器处理完数据后,再发送 FIN,表示正式关闭。
  4. 客户端回复 ACK,进入 TIME_WAIT 状态,等待一段时间后才真正断开连接。

🔹 为什么是四次挥手?

  • 因为 TCP 是全双工的,通信双方需要独立关闭自己的数据传输通道
  • FIN 只能表示“我不再发送数据”,但还可以继续接收数据,所以需要 ACK 进行确认。

6. 现实中的 TCP 连接关闭

  • 普通 HTTP(短连接)
    • 每次请求/响应后,客户端主动关闭,服务器进入 CLOSE_WAIT
  • 长连接(HTTP/1.1、WebSocket)
    • 连接会保持一段时间,除非客户端或服务器主动关闭。
  • 高并发优化
    • 服务器会优化 TIME_WAIT 机制,减少端口占用。


http://www.kler.cn/a/576808.html

相关文章:

  • 游戏引擎学习第144天
  • 用AI学编程3——Java学习1
  • 轻量级 Transformer 架构多模态预训练框架
  • set、LinkedHashSet和TreeSet的区别、Map接口常见方法、Collections 工具类使用
  • Restful 接口设计规范
  • 从高资源到低资源语言的全覆盖:Manus AI的数据革命与迁移学习策略
  • 从0开始,手搓Tomcat
  • Python——计算机网络
  • 香橙派首款高性能开源 RISC-V 开发板 OrangePi RV 即将开售
  • 【Manus资料合集】激活码内测渠道+《Manus Al:Agent应用的ChatGPT时刻》(附资源)
  • LeetCode 解题思路 12(Hot 100)
  • .NET Core全屏截图,C#全屏截图
  • C++蓝桥杯基础篇(八)
  • python爬虫系列课程6:js定时器
  • Python SQLite3 保姆级教程:从零开始学数据库操作
  • MYSQL之创建数据库和表
  • 队列相关练习
  • springboot多模块项目中IDEA报错找不到符号
  • 基于51单片机的六路抢答器proteus仿真
  • DeepSeek的安全威胁与国际象棋水平测试