所有过程

当你在网页端打开一个页面时,会发生一系列复杂的步骤,涉及网络通信、服务器处理、浏览器渲染等多个环节。以下是详细的技术分解:

  1. 导航开始

    • 用户在浏览器地址栏输入 URL,或点击页面上的链接,触发导航动作 16
    • 浏览器开始处理输入,检查是否为有效的 URL。
  2. DNS 解析

    • 浏览器需要将域名(例如 www.google.com)转换为服务器的 IP 地址 123
    • 本地 DNS 缓存:浏览器首先检查本地 DNS 缓存,看是否已存在该域名的 IP 地址。
    • 操作系统 DNS 缓存:如果浏览器缓存没有,操作系统会检查其 DNS 缓存。
    • 路由器 DNS 缓存:如果操作系统缓存也没有,请求会发送到路由器,路由器通常也有 DNS 缓存。
    • ISP DNS 服务器:如果以上各级缓存均未命中,请求会发送到互联网服务提供商(ISP)的 DNS 服务器。
    • 递归查询:ISP 的 DNS 服务器可能会递归地查询根域名服务器、顶级域名服务器(如 .com.net)和权威域名服务器,直到找到目标 IP 地址 2
    • DNS 记录类型:DNS 服务器返回与域名相关的 DNS 记录,其中 A 记录包含 IPv4 地址,AAAA 记录包含 IPv6 地址。
  3. 建立 TCP 连接

    • 一旦获取到目标服务器的 IP 地址,浏览器会尝试与服务器建立 TCP 连接 13
    • 三次握手:TCP 连接的建立需要经过三次握手过程:
      1. 客户端发送 SYN(同步)包到服务器。
      2. 服务器回复 SYN-ACK(同步-确认)包。
      3. 客户端发送 ACK(确认)包,连接建立完成。
  4. TLS 协商(如果使用 HTTPS)

    • 如果 URL 使用 HTTPS 协议,浏览器需要与服务器进行 TLS(Transport Layer Security)协商,以建立安全连接 13
    • TLS 握手
      1. 客户端发送 ClientHello 消息,包含客户端支持的 TLS 版本、加密算法等信息。
      2. 服务器回复 ServerHello 消息,选择 TLS 版本和加密算法,并发送服务器证书。
      3. 客户端验证服务器证书的有效性(例如,检查证书是否由受信任的 CA 签发,证书是否过期)。
      4. 客户端生成一个 pre-master secret,使用服务器的公钥加密后发送给服务器。
      5. 服务器使用私钥解密 pre-master secret。
      6. 客户端和服务器使用 pre-master secret 协商生成 master secret,用于后续的对称加密通信。
  5. 发送 HTTP 请求

    • 在 TCP 连接(或 TLS 连接)建立完成后,浏览器向服务器发送 HTTP 请求 134
    • 请求方法:通常是 GET 请求,用于获取页面资源。也可以是 POST 请求,用于提交数据。
    • 请求头:包含浏览器信息(User-Agent)、接受的媒体类型(Accept)、Cookie 等。
  6. 服务器处理请求

    • 服务器接收到 HTTP 请求后,进行处理 3
    • Web 服务器:如 Nginx 或 Apache,接收请求并根据配置进行处理。
    • 应用服务器:如果请求需要动态内容,Web 服务器会将请求转发给应用服务器,如 Node.js、Python (Django/Flask) 或 Java (Spring)。
    • 数据库查询:应用服务器可能需要查询数据库,以获取动态数据。
  7. 服务器返回 HTTP 响应

    • 服务器生成 HTTP 响应,包含响应头和响应体 1
    • 响应状态码:如 200 OK(成功)、404 Not Found(未找到)、500 Internal Server Error(服务器内部错误)等。
    • 响应头:包含内容类型(Content-Type)、内容长度(Content-Length)、缓存策略(Cache-Control)等。
    • 响应体:包含 HTML、CSS、JavaScript、图片等资源。
  8. 浏览器渲染页面

    • 浏览器接收到 HTTP 响应后,开始渲染页面 35.
    • 解析 HTML:浏览器解析 HTML 标记,构建 DOM(Document Object Model)树。
    • 解析 CSS:浏览器解析 CSS 样式,构建 CSSOM(CSS Object Model)树。
    • 构建渲染树:浏览器将 DOM 树和 CSSOM 树合并,构建渲染树(Render Tree),渲染树只包含需要显示的节点。
    • 布局(Layout):浏览器计算每个节点在页面中的位置和大小。
    • 绘制(Paint):浏览器将渲染树中的节点绘制到屏幕上。
    • JavaScript 执行:如果 HTML 中包含 JavaScript 代码,浏览器会执行这些代码,JavaScript 可以修改 DOM 树和 CSSOM 树,从而改变页面的内容和样式。
  9. 加载和执行外部资源

    • 在解析 HTML 过程中,浏览器会发现外部资源链接,如 CSS 文件、JavaScript 文件、图片等 15.
    • 浏览器会并行下载这些资源,并根据资源类型进行处理。
    • CSS 文件会用于构建 CSSOM 树。
    • JavaScript 文件会被执行,执行过程中可能会修改 DOM 树和 CSSOM 树。
    • 图片会被解码并显示在页面上。

代码示例

Golang + Gin

以下是一个简单的例子,展示了如何使用 Golang 的 Gin 框架来处理 HTTP 请求并返回 HTML 响应。

package main
 
import (
 "net/http"
 "github.com/gin-gonic/gin"
)
 
func main() {
 router := gin.Default()
 
 // 定义一个处理 GET 请求的路由
 router.GET("/", func(c *gin.Context) {
  // 返回 HTML 响应
  c.HTML(http.StatusOK, "index.html", gin.H{
   "title": "Hello, Devv!",
   "message": "欢迎来到我的网页!",
  })
 })
 
 // 加载 HTML 模板文件
 router.LoadHTMLGlob("templates/*")
 
 // 启动 HTTP 服务器,监听 8080 端口
 router.Run(":8080")
}

Html

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{ .title }}</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
        background-color: #f4f4f4;
        color: #333;
        text-align: center;
      }
      .container {
        max-width: 800px;
        margin: 50px auto;
        padding: 20px;
        background-color: #fff;
        border-radius: 8px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
      }
      h1 {
        color: #0056b3;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>{{ .title }}</h1>
      <p>{{ .message }}</p>
    </div>
  </body>
</html>

运行代码

  1. 创建项目目录

    mkdir web-page-example
    cd web-page-example
    go mod init web-page-example
  2. 创建 main.go 文件

    将上述 Golang 代码复制到 main.go 文件中。

  3. 创建 templates 目录和 index.html 文件

    mkdir templates

    将上述 HTML 代码复制到 templates/index.html 文件中。

  4. 下载 Gin 框架

    go get -u github.com/gin-gonic/gin
  5. 运行程序

    go run main.go
  6. 验证

    在浏览器中访问 http://localhost:8080,你应该能看到页面显示 “Hello, Devv!” 和 “欢迎来到我的网页!”。

这个例子展示了服务器如何接收请求、处理请求,并返回 HTML 响应。浏览器接收到响应后,会解析 HTML 并渲染页面。

image-20250310103140319