World Wide Web
万维网是什么
万维网(World Wide Web,WWW)并非某种特殊的计算机网络——它是一个大规模的、联机式的信息储藏所,是运行在因特网上的一个分布式应用。万维网利用网页之间的超链接,将不同网站的网页链接成一张逻辑上的信息网。
万维网的核心思想很简单:用户点击链接,浏览器向对应服务器请求文档,服务器将文档返回给浏览器,浏览器渲染展示。背后的关键协议就是 HTTP(超文本传输协议)。
URL:统一资源定位符
万维网上的每一个文档(网页、图片、视频等)在整个因特网范围内都有唯一的标识符——统一资源定位符 URL。
URL 的一般格式:
$$
\text{<协议>://<主机>:<端口>/<路径>}
$$
| 组成部分 | 说明 | 示例 |
|---|---|---|
| 协议 | 访问资源所用的应用层协议 | http、https、ftp |
| 主机 | 存放资源的服务器的域名或 IP 地址 | www.hnust.edu.cn |
| 端口 | 服务器监听的端口号(可省略,使用协议默认端口) | HTTP 默认 80,HTTPS 默认 443 |
| 路径 | 资源在服务器上的位置路径 | /index.htm、/images/logo.png |
例如 http://www.hnust.edu.cn:80/index.htm 中:
- 协议
http→ 使用 HTTP。 - 主机
www.hnust.edu.cn→ 湖南科技大学 Web 服务器。 - 端口
80→ HTTP 默认端口,通常省略不写。 - 路径
/index.htm→ 请求网站首页文件。
用户通常只需要在浏览器地址栏输入域名和路径。协议和端口如果使用默认值,浏览器会自动补充。
万维网文档
万维网服务器上的文档通常由三种类型的文件构成:
- HTML(超文本标记语言):定义网页的结构和内容。包含文本、图片、链接等元素,由浏览器解析并渲染。
- CSS(层叠样式表):定义网页的样式。控制颜色、字体、布局等视觉呈现。
- JavaScript:定义网页的行为。实现交互功能、动态内容更新等。
这些文档可以是事先设计好的静态页面,也可以是服务器后端程序根据用户请求自动生成的动态页面。无论哪种,最终都需要通过 HTTP 从服务器传送给用户浏览器进行解析和渲染。
HTTP 的操作过程
超文本传输协议(HTTP)定义了浏览器(HTTP 客户)如何向万维网服务器(HTTP 服务器)请求万维网文档,以及服务器如何把文档传送给浏览器。
HTTP 的基本操作过程:
- 浏览器解析 URL,得到服务器的域名和端口号。
- 浏览器与服务器建立 TCP 连接(HTTP 默认端口 80)。
- 浏览器通过 TCP 连接发送 HTTP 请求报文。
- 服务器收到请求报文后,执行相应操作,发回 HTTP 响应报文。
- 根据 HTTP 版本和首部设置决定 TCP 连接是否释放。
- 浏览器解析响应报文中的文档内容并渲染。
HTTP/1.0 与 HTTP/1.1
HTTP 有两个主要版本,它们的核心区别在于如何使用 TCP 连接。
非持续连接(HTTP/1.0)
HTTP/1.0 默认使用非持续连接(non-persistent connection):浏览器为每个请求对象单独建立一个 TCP 连接,服务器返回该对象后即释放连接。
对于每个对象,时间开销为 2 RTT + 文档传输时延:
- RTT1:TCP 三报文握手建立连接。
- RTT2:HTTP 请求报文发出,到 HTTP 响应报文第一个字节到达。
如果一个网页包含 $n$ 个引用对象(图片、CSS、JS 等),就需要建立 $n+1$ 个 TCP 连接($n$ 个对象 + 1 个 HTML 页面),总时延巨大。
为减小时延,HTTP/1.0 浏览器通常建立多个并行的 TCP 连接同时请求多个对象。但这会大量占用服务器资源,加重服务器负担。
持续连接(HTTP/1.1)
HTTP/1.1 默认使用持续连接(persistent connection):一个 TCP 连接建立后,可以连续传送多个 HTTP 请求和响应,直到明确断开。这避免了每个对象都经历 TCP 握手和慢开始的代价。
HTTP/1.1 的持续连接有两种工作方式:
| 非流水线方式 | 流水线方式 | |
|---|---|---|
| 请求顺序 | 客户发送一个请求 → 收到响应 → 再发下一个请求 | 客户连续发送多个请求,不逐个等待响应 |
| RTT 等待 | 每个后续对象通常仍增加 1 RTT | 一批请求可共用约 1 RTT 的等待 |
| RTT 开销 | 第一个请求后,每个后续请求仍需 1 RTT | 一批请求只需 1 RTT 的等待时间 |
| 实现复杂度 | 简单 | 较复杂(需匹配请求与响应顺序) |
| 使用情况 | 最简单、最常见的持续连接方式 | HTTP/1.1 允许使用,但浏览器实践中很少启用 |
流水线方式虽然减少 RTT 等待,但服务器必须按请求顺序返回响应。若前一个响应生成或传输很慢,后续响应会被它挡住,形成 HTTP/1.1 队头阻塞。HTTP/2 的多路复用消除了 HTTP 层按响应顺序造成的阻塞,但其 TCP 连接仍可能因丢包发生传输层队头阻塞;HTTP/3 改用 QUIC 后才进一步隔离不同流之间的丢包影响。
HTTP/1.0 与 HTTP/1.1 对比
| 维度 | HTTP/1.0 | HTTP/1.1 |
|---|---|---|
| 连接方式 | 默认非持续连接 | 默认持续连接 |
| TCP 连接数 | 每请求一个对象建立一个 TCP 连接 | 一个 TCP 连接可传送多个请求和响应 |
| RTT 开销 | 每个对象 2 RTT | 首次 2 RTT,后续对象可复用连接 |
| 流水线 | 不支持 | 协议允许,但实际很少使用 |
Host 首部 |
可选 | 必须——支持虚拟主机(同一 IP 开放多个网站) |
| 方法与首部 | 基本方法和首部较少 | 方法和首部机制更丰富 |
| 缓存控制 | 较简单 | 更完善(Cache-Control 等) |
HTTP 报文格式
HTTP 报文分为两种:请求报文和响应报文。两者的结构类似,都是 ASCII 文本(人类可读)。
请求报文
HTTP 请求报文包含请求行、首部行和可选的实体主体;首部与实体主体之间用空行分隔。按报文中的可见区域可列为:
| 部分 | 内容 | 说明 |
|---|---|---|
| 请求行 | 方法 + 空格 + URL + 空格 + 版本 + CRLF | 第一行,必须。GET /index.htm HTTP/1.1 |
| 首部行 | 首部字段名 + : + 空格 + 值 + CRLF |
可有多行。如 Host:、Connection:、User-Agent: |
| 空行 | CRLF | 首部行结束标志 |
| 实体主体 | 数据 | 通常不使用(GET 请求一般无实体主体) |
常用 HTTP 请求方法:
| 方法 | 含义 |
|---|---|
GET |
请求读取 URL 所标志的文档 |
HEAD |
请求读取 URL 所标志文档的首部(不返回文档体) |
POST |
向服务器提交数据(如表单) |
PUT |
在指明的 URL 下存储一个文档 |
DELETE |
删除 URL 所标志的文档 |
CONNECT |
用于代理服务器 |
OPTIONS |
请求一些选项信息 |
TRACE |
用于环回测试 |
PATCH |
对 PUT 的补充,用于局部更新 |
响应报文
HTTP 响应报文包含状态行、首部行和可选的实体主体,同样用空行分隔首部与主体:
| 部分 | 内容 | 说明 |
|---|---|---|
| 状态行 | 版本 + 空格 + 状态码 + 空格 + 短语 + CRLF | 第一行,必须。HTTP/1.1 200 OK |
| 首部行 | 同请求报文 | 如 Content-Type:、Content-Length: |
| 空行 | CRLF | 首部行结束标志 |
| 实体主体 | 返回的文档内容 | 如 HTML 文件 |
常见 HTTP 状态码:
| 状态码 | 短语 | 含义 |
|---|---|---|
200 |
OK | 请求成功 |
202 |
Accepted | 已接受请求 |
301 |
Moved Permanently | 永久重定向 |
304 |
Not Modified | 文档未修改(用于缓存验证) |
400 |
Bad Request | 请求报文有语法错误 |
404 |
Not Found | 服务器找不到请求的资源 |
500 |
Internal Server Error | 服务器内部错误 |
Cookie:让 HTTP “记住”用户
HTTP 本身是无状态的——服务器不保存任何有关客户的历史请求信息。这意味着如果用户连续两次请求同一个网站,服务器无法知道这是同一个用户。
Cookie 是一种在无状态的 HTTP 之上维护用户状态的机制。
Cookie 的基本工作流程:
- 用户初次访问网站时,浏览器发送 HTTP 请求报文(不含 Cookie)。
- 服务器为其生成一个唯一的 Cookie 识别码,并在后端数据库中创建记录。
- 服务器在 HTTP 响应报文中通过
Set-Cookie首部行将识别码返回给浏览器。 - 浏览器将识别码存储在 Cookie 文件中。
- 用户之后每次访问该网站时,浏览器自动从 Cookie 文件中取出识别码,放入 HTTP 请求报文的
Cookie首部行中。 - 服务器根据识别码从数据库中取出用户信息,返回个性化内容。
Cookie 的关键首部:
- 响应报文:
Set-Cookie: <识别码>(服务器设置 Cookie)。 - 请求报文:
Cookie: <识别码>(浏览器回传 Cookie)。
Cookie 只是维护状态的诸多方法之一。它常用于”记住我”、购物车、个性化推荐等场景。
万维网缓存与代理服务器
万维网缓存(Web Cache)把最近的一些请求和响应暂存在本地,以提高万维网的效率。缓存可以位于客户机中;位于客户与原始服务器之间的中间系统上的 Web 缓存称为代理服务器。
代理服务器的工作方式:
| 情况 | 代理服务器行为 |
|---|---|
| 缓存命中 | 请求到达代理服务器 → 缓存中有对应文档且未过期 → 直接返回给客户 |
| 缓存未命中 | 请求到达代理服务器 → 缓存中无对应文档 → 代理服务器向原始服务器请求 → 存入缓存 → 返回给客户 |
| 缓存过期 | 代理服务器向原始服务器发送验证请求(携带 If-modified-since 头)→ 原始服务器判断是否修改 |
缓存一致性
原始服务器通常为每个响应的对象设定两个时间字段:
- **
Last-Modified**:文档最后修改时间。 - **
Expires**:文档有效期。
当代理服务器中的文档过期后,代理服务器向原始服务器发送验证请求,携带 If-Modified-Since 首部(值为该文档的修改日期):
- 文档未修改 → 原始服务器返回
304 Not Modified(不含实体主体),代理服务器更新文档有效期。 - 文档已修改 → 原始服务器返回
200 OK和新文档,代理服务器更新缓存和有效期。
代理服务器的作用:
- 减少出口带宽:校园网或公司网络内的用户请求相同资源时,只需一次从因特网获取。
- 降低访问延迟:缓存命中时,响应从本地代理服务器返回,远快于从原始服务器获取。
- 减轻原始服务器负载:大量重复请求被代理服务器拦截,不到达原始服务器。