万维网是什么

万维网(World Wide Web,WWW)并非某种特殊的计算机网络——它是一个大规模的、联机式的信息储藏所,是运行在因特网上的一个分布式应用。万维网利用网页之间的超链接,将不同网站的网页链接成一张逻辑上的信息网。

万维网的核心思想很简单:用户点击链接,浏览器向对应服务器请求文档,服务器将文档返回给浏览器,浏览器渲染展示。背后的关键协议就是 HTTP(超文本传输协议)。

URL:统一资源定位符

万维网上的每一个文档(网页、图片、视频等)在整个因特网范围内都有唯一的标识符——统一资源定位符 URL

900

URL 的一般格式:

$$
\text{<协议>://<主机>:<端口>/<路径>}
$$

组成部分 说明 示例
协议 访问资源所用的应用层协议 httphttpsftp
主机 存放资源的服务器的域名或 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 的基本操作过程:

  1. 浏览器解析 URL,得到服务器的域名和端口号。
  2. 浏览器与服务器建立 TCP 连接(HTTP 默认端口 80)。
  3. 浏览器通过 TCP 连接发送 HTTP 请求报文
  4. 服务器收到请求报文后,执行相应操作,发回 HTTP 响应报文
  5. 根据 HTTP 版本和首部设置决定 TCP 连接是否释放。
  6. 浏览器解析响应报文中的文档内容并渲染。

HTTP/1.0 与 HTTP/1.1

HTTP 有两个主要版本,它们的核心区别在于如何使用 TCP 连接。

非持续连接(HTTP/1.0)

HTTP/1.0 默认使用非持续连接(non-persistent connection):浏览器为每个请求对象单独建立一个 TCP 连接,服务器返回该对象后即释放连接。

900

对于每个对象,时间开销为 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 握手和慢开始的代价。

900

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 文本(人类可读)。

900

请求报文

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 的基本工作流程:

  1. 用户初次访问网站时,浏览器发送 HTTP 请求报文(不含 Cookie)。
  2. 服务器为其生成一个唯一的 Cookie 识别码,并在后端数据库中创建记录。
  3. 服务器在 HTTP 响应报文中通过 Set-Cookie 首部行将识别码返回给浏览器。
  4. 浏览器将识别码存储在 Cookie 文件中。
  5. 用户之后每次访问该网站时,浏览器自动从 Cookie 文件中取出识别码,放入 HTTP 请求报文的 Cookie 首部行中。
  6. 服务器根据识别码从数据库中取出用户信息,返回个性化内容。

Cookie 的关键首部:

  • 响应报文:Set-Cookie: <识别码>(服务器设置 Cookie)。
  • 请求报文:Cookie: <识别码>(浏览器回传 Cookie)。

Cookie 只是维护状态的诸多方法之一。它常用于”记住我”、购物车、个性化推荐等场景。

万维网缓存与代理服务器

万维网缓存(Web Cache)把最近的一些请求和响应暂存在本地,以提高万维网的效率。缓存可以位于客户机中;位于客户与原始服务器之间的中间系统上的 Web 缓存称为代理服务器

代理服务器的工作方式:

情况 代理服务器行为
缓存命中 请求到达代理服务器 → 缓存中有对应文档且未过期 → 直接返回给客户
缓存未命中 请求到达代理服务器 → 缓存中无对应文档 → 代理服务器向原始服务器请求 → 存入缓存 → 返回给客户
缓存过期 代理服务器向原始服务器发送验证请求(携带 If-modified-since 头)→ 原始服务器判断是否修改

缓存一致性

原始服务器通常为每个响应的对象设定两个时间字段:

  • **Last-Modified**:文档最后修改时间。
  • **Expires**:文档有效期。

当代理服务器中的文档过期后,代理服务器向原始服务器发送验证请求,携带 If-Modified-Since 首部(值为该文档的修改日期):

  • 文档未修改 → 原始服务器返回 304 Not Modified(不含实体主体),代理服务器更新文档有效期。
  • 文档已修改 → 原始服务器返回 200 OK 和新文档,代理服务器更新缓存和有效期。

代理服务器的作用:

  • 减少出口带宽:校园网或公司网络内的用户请求相同资源时,只需一次从因特网获取。
  • 降低访问延迟:缓存命中时,响应从本地代理服务器返回,远快于从原始服务器获取。
  • 减轻原始服务器负载:大量重复请求被代理服务器拦截,不到达原始服务器。