所有过程
当你在网页端打开一个页面时,会发生一系列复杂的步骤,涉及网络通信、服务器处理、浏览器渲染等多个环节。以下是详细的技术分解:
-
导航开始
-
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 地址。
- 浏览器需要将域名(例如
-
建立 TCP 连接
-
TLS 协商(如果使用 HTTPS)
- 如果 URL 使用 HTTPS 协议,浏览器需要与服务器进行 TLS(Transport Layer Security)协商,以建立安全连接 13。
- TLS 握手:
- 客户端发送 ClientHello 消息,包含客户端支持的 TLS 版本、加密算法等信息。
- 服务器回复 ServerHello 消息,选择 TLS 版本和加密算法,并发送服务器证书。
- 客户端验证服务器证书的有效性(例如,检查证书是否由受信任的 CA 签发,证书是否过期)。
- 客户端生成一个 pre-master secret,使用服务器的公钥加密后发送给服务器。
- 服务器使用私钥解密 pre-master secret。
- 客户端和服务器使用 pre-master secret 协商生成 master secret,用于后续的对称加密通信。
-
发送 HTTP 请求
-
服务器处理请求
- 服务器接收到 HTTP 请求后,进行处理 3。
- Web 服务器:如 Nginx 或 Apache,接收请求并根据配置进行处理。
- 应用服务器:如果请求需要动态内容,Web 服务器会将请求转发给应用服务器,如 Node.js、Python (Django/Flask) 或 Java (Spring)。
- 数据库查询:应用服务器可能需要查询数据库,以获取动态数据。
-
服务器返回 HTTP 响应
- 服务器生成 HTTP 响应,包含响应头和响应体 1。
- 响应状态码:如 200 OK(成功)、404 Not Found(未找到)、500 Internal Server Error(服务器内部错误)等。
- 响应头:包含内容类型(Content-Type)、内容长度(Content-Length)、缓存策略(Cache-Control)等。
- 响应体:包含 HTML、CSS、JavaScript、图片等资源。
-
浏览器渲染页面
- 浏览器接收到 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 树,从而改变页面的内容和样式。
-
加载和执行外部资源
代码示例
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>运行代码
-
创建项目目录
mkdir web-page-example cd web-page-example go mod init web-page-example -
创建
main.go文件将上述 Golang 代码复制到
main.go文件中。 -
创建
templates目录和index.html文件mkdir templates将上述 HTML 代码复制到
templates/index.html文件中。 -
下载 Gin 框架
go get -u github.com/gin-gonic/gin -
运行程序
go run main.go -
验证
在浏览器中访问
http://localhost:8080,你应该能看到页面显示 “Hello, Devv!” 和 “欢迎来到我的网页!”。
这个例子展示了服务器如何接收请求、处理请求,并返回 HTML 响应。浏览器接收到响应后,会解析 HTML 并渲染页面。
