计算机网络之应用层

网络应用体系结构

目前主流的网络应用体系结构主要有以下三种:

客户端-服务器(Client-Server)体系结构

这是目前最主流、最常见的网络应用结构。

  1. 核心概念
  • 服务器 (Server):
    • 地位: 始终开启的主机。
    • 功能: 持续提供服务,拥有固定的、永久的IP地址,并负责存储数据和运行应用的核心逻辑。例如,Web服务器、邮件服务器。
  • 客户端 (Client):
    • 地位: 需要服务时请求的主机。
    • 功能: 与服务器通信,获取服务,通常是终端用户设备(PC、手机等)。客户端可以是动态IP地址,且不需要始终开启。
  • 交互模式: 客户端发起请求,服务器响应请求。
  1. 优点
  • 集中控制和管理: 数据和应用逻辑集中在服务器上,便于安全管理、备份和维护。
  • 可扩展性好: 通过增加或升级服务器(如使用负载均衡),可以支持更多客户端。
  • 安全性高: 服务器可以实施严格的身份验证和授权。
  1. 缺点
  • 单点故障风险(SPOF): 如果中心服务器出现故障,整个应用服务可能会中断。
  • 网络瓶颈: 所有请求都集中在服务器端,在高并发情况下可能成为性能瓶颈。
  1. 典型应用
  • Web应用: 浏览器(客户端)访问网站服务器。
  • FTP: 文件传输。
  • 电子邮件: 客户端访问邮件服务器。

对等(Peer-to-Peer, P2P)体系结构

  1. 核心概念
  • 对等方 (Peer):
    • 地位: 任何主机既可以作为客户端向其他主机请求服务,也可以作为服务器向其他主机提供服务。
    • 特点: 每个对等方都是平等的,没有固定的中心服务器。节点间歇性连接,且IP地址可能频繁变动。
  • 交互模式: 对等方之间直接通信,共享资源。
  1. 优点
  • 高度可扩展性: 系统的容量和带宽随着用户的增加而增加。
  • 健壮性/抗毁性: 没有单点故障,部分节点失效不影响整体运行。
  • 成本低廉: 无需昂贵的服务器基础设施。
  1. 缺点
  • 复杂性高: 难以管理和维护,资源的搜索和定位相对复杂。
  • 安全性挑战: 难以实施集中化的安全策略和身份验证。
  • 性能波动: 资源由用户提供,网络性能和资源可用性不稳定。
  1. 典型应用
  • 文件共享: BitTorrent、eMule。
  • 加密货币网络: 比特币等(节点同时作为客户端和服务器)。
  • VolP应用: 一些早期的网络电话服务。

混合(Hybrid)体系结构

混合结构将客户端-服务器模式的集中管理优势与P2P模式的分布式资源共享优势结合起来。

  1. 核心概念
  • 中心服务器: 用于进行集中化管理,例如用户登录、资源索引、对等方状态跟踪等。
  • 对等方: 一旦连接建立,数据传输则直接在对等方之间进行。
  1. 工作流程
  • 连接/定位: 用户登录到中心服务器。
  • 查询: 用户向中心服务器查询所需资源的索引或某个对等方的地址。
  • 传输: 获得信息后,用户直接与提供资源的对等方建立P2P连接,进行实际的数据传输。
  1. 典型应用
  • 即时通讯(IM): QQ、微信等应用。用户登录和状态信息(谁在线)由服务器管理,但语音/视频通话等大流量数据传输,有时会尝试在用户之间直接进行P2P连接。
  • 某些P2P文件共享系统: 使用中心服务器来维护索引。

简要对比总结

特征 客户端-服务器 (C/S) 对等 (P2P) 混合 (Hybrid)
中心化 高度集中(有永久性服务器) 完全分散(没有中心服务器) 部分集中(用于管理和索引)
角色 严格区分(客户端/服务器) 角色对等(同时是客户端/服务器) 分阶段角色(服务器用于索引,Peer用于传输)
可扩展性 需要服务器升级或集群 随用户数自然增强 集中管理部分有限制
安全性 易于实施集中安全 难以保证 集中部分安全可控
健壮性 易受单点故障影响 高度健壮,无单点故障 优于C/S,劣于纯P2P

Web和HTTP

HTTP概述

Web的应⽤层协议是超⽂本传输协议(HTTP),它是Web的核⼼,在[RFC1945]、[RFC7230]和[RFC7540]中进⾏了定义。HTTP由两个程序实现:⼀个客户程序和⼀个服务器程序。客户程序和服务器程序运⾏在不同的端系统中,通过交换HTTP报⽂进⾏会话。HTTP定义了这些报⽂的结构以及客户和服务器进⾏报⽂交换的⽅式。

Web页⾯(Web page)(也叫⽂档)是由对象组成的。⼀个对象只是⼀个⽂件,诸如⼀个HTML.⽂件、⼀个JPEG图形、⼀个JavaScript⽂件、⼀个CCS样式表⽂件或⼀个视频⽚段,它们可通过⼀个URL寻址。多数Web页⾯含有⼀个HTML基本⽂件(baseHTMLfile)以及⼏个引⽤对象。例如,如果⼀个Web页⾯包含HTML⽂本和5个JPEG图形,那么这个web页⾯有6个对象:⼀个HTML基本⽂件加5个图形。HTML基本⽂件通过对象的URL引⽤页⾯中的其他对象。

当⽤户请求⼀个web页⾯(如点击⼀个超链接)时,浏览器向服务器发出对该页⾯中所包含对象的HTTP请求报⽂,服务器接收到请求并⽤包含这些对象的HTTP响应报⽂进⾏响应。

HTTP使⽤TCP作为它的⽀撑运输协议(⽽不是在UDP上运⾏)。HTTP客户⾸先发起⼀个与服务器的TCP连接。⼀旦连接建⽴,该浏览器和服务器进程就可以通过套接字接口访问TCP。客户端的套接字接口是客户进程与TCP连接之间的门,服务器端的套接字接口则是服务器进程与TCP连接之间的门。客户向它的套接字接口发送HTTP请求报⽂并从它的套接字接口接收HTTP响应报⽂。类似地,服务器从它的套接字接口接收HTTP请求报⽂并向它的套接字接口发送HTTP响应报⽂。

HTTP是一个无状态协议,不保存用户的任何信息。
FTP、SMTP、telnet/ssh、WebSocket、TCP都是有状态的。

类型 协议 状态性 原因
传输层 TCP 有状态 需要维护连接状态
传输层 UDP 无状态 每个报文独立
应用层 HTTP 无状态 每次请求独立
应用层 FTP、SMTP、SSH、WebSocket 有状态 需要维持会话上下文
网络层 IP、ICMP 无状态 无连接状态维护

非持续连接和持续连接

非持续连接:每个请求/响应由一个单独的TCP连接发送。
持续连接:所有请求/响应由相同的TCP连接发送。

HTTP1.0默认采用非持续连接,HTTP1.1开始默认采用持续连接

HTTP报文格式

分为请求报文响应报文

请求报文

格式如下:

1
2
3
4
<请求行>
<请求头部字段>
<空行>
<请求体>

请求行

1
<Method> <Request-URI> <HTTP-Version>

例如:

1
GET /index.html HTTP/1.1

请求头部

以“键: 值”形式表示,用于说明请求的附加信息:

1
2
3
4
5
6
7
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: zh-CN
Connection: keep-alive
Content-Type: application/json
Content-Length: 34

请求体

请求体是可选的,主要在以下请求中使用:
POST(表单提交、JSON 数据等)
PUT(上传或更新资源)
PATCH

示例(POST 发送 JSON):

1
2
3
4
5
6
POST /api/login HTTP/1.1
Host: www.example.com
Content-Type: application/json
Content-Length: 45

{"username": "Alice", "password": "123456"}

响应报文

格式如下:

1
2
3
4
<状态行>
<响应头部字段>
<空行>
<响应体>

状态行

1
<HTTP-Version> <Status-Code> <Reason-Phrase>

例如:

1
HTTP1.1 200 OK

响应头部

1
2
3
4
5
Date: Thu, 13 Nov 2025 01:45:00 GMT
Server: nginx/1.24
Content-Type: text/html; charset=utf-8
Content-Length: 1024
Connection: keep-alive

响应体

包含服务器返回的内容,比如:
HTML页面
JSON数据
图片/文件内容

1
2
3
4
5
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 28

{"code": 0, "msg": "success"}

Cookie 主要是为了解决HTTP无状态导致的“服务器记不住客户端”的问题。

HTTP是无状态协议,每个请求都是独立的,服务器不会自动记得上次是谁发的请求。
Cookie的核心任务,就是让服务器能识别同一个用户的连续请求

Cookie 的常见任务分类如下:

任务类别 说明 示例
1. 会话管理(Session Management) 维持用户登录状态、购物车、浏览状态等。 登录后,Cookie 中存有 session_id,服务器据此识别当前用户。
2. 个性化设置(Personalization) 保存用户偏好,如语言、主题、字体大小。 lang=zh-CNtheme=dark
3. 跟踪与分析(Tracking / Analytics) 统计用户访问次数、来源或行为,用于广告和分析。 user_uuid=abcd1234
4. 安全控制(Security) 管理 CSRF 令牌、防重放、验证设备。 csrftoken=xyz
5. 状态缓存 临时保存上次访问的资源、表单输入状态。 表单恢复、导航状态保持

Cookie是由服务器生成,存储在客户端,由浏览器自动携带的。

  1. 服务器发送 Cookie(Set-Cookie)

服务器通过响应头告诉浏览器“请你保存一个 Cookie”。

示例:

1
2
3
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: sessionId=abc123; Path=/; Domain=example.com; HttpOnly; Max-Age=3600

含义:

  • 浏览器收到这条 Set-Cookie 后,会保存键值对 sessionId=abc123
  • 同时记录属性(作用域、有效期、安全限制)

  1. 浏览器保存 Cookie

浏览器内部会为每个域维护一个“Cookie 存储区”。

当收到 Set-Cookie

  • 浏览器检查是否允许保存(根据 SameSite、安全策略等)
  • 将 Cookie 保存到内存或磁盘(取决于是 session 还是持久化)
  • 记下 Domain、Path、Expires/Max-Age 等属性

存储示意(浏览器内部表):

Name Value Domain Path ExpireTime Secure HttpOnly
sessionId abc123 example.com / +1小时
  1. 浏览器发送 Cookie(请求时自动附带)

当你再次访问同一网站(域、路径匹配)时:

浏览器自动在请求头中加入 Cookie:

1
2
3
GET /user/profile HTTP/1.1
Host: example.com
Cookie: sessionId=abc123

浏览器只会附带符合以下条件的 Cookie:

  • 请求域名匹配 Cookie 的 Domain
  • 请求路径匹配 Cookie 的 Path
  • 当前时间未超过过期时间
  • 如果是 HTTPS,则 Secure Cookie 只在加密连接上传输
  • 如果有 SameSite 限制,则要满足跨站策略
  1. 服务器接收并解析 Cookie

服务器端在收到请求后:

  • 读取请求头中的 Cookie
  • 解析出键值对;
  • 根据 sessionId 去服务器端的 Session 表中查找用户状态;
  • 确定当前是谁、是否已登录等。

服务器端伪代码示例:

1
2
3
4
string cookie = request.getHeader("Cookie");
// 例如 cookie = "sessionId=abc123; lang=zh-CN"
auto session_id = parse(cookie)["sessionId"];
User *user = session_store.get(session_id);

然后,服务器就能基于这个会话信息提供个性化服务。

阶段 由谁发起 说明
创建 服务器(Set-Cookie) 服务器告诉浏览器保存 Cookie
存储 浏览器 浏览器按规则保存
发送 浏览器 请求时自动附带符合条件的 Cookie
使用 服务器 识别用户、维持会话
失效 浏览器 到期时间到、清除缓存或被新 Cookie 覆盖

安全与行为

属性 浏览器行为 作用
Secure 只在 HTTPS 上传输 防止被中间人窃听
HttpOnly JS 无法访问(document.cookie) 防止 XSS 窃取
SameSite 控制跨站是否附带 防御 CSRF
Domain/Path 控制作用范围 避免滥发
Expires/Max-Age 控制过期时间 生命周期管理
  1. 用户访问登录页
    → 浏览器发请求(无 Cookie)

  2. 用户提交表单(用户名/密码)
    → 服务器验证成功
    → 服务器返回响应头:

1
Set-Cookie: sessionId=xyz123; Path=/; HttpOnly; Secure; SameSite=Lax
  1. 浏览器保存 Cookie
    sessionId=xyz123 被记录

  2. 用户刷新或访问其他页面
    → 浏览器自动在请求头中加:

1
Cookie: sessionId=xyz123
  1. 服务器识别 session
    → 找到对应用户信息
    → 响应内容展示“欢迎回来,Alice!”

Web缓存

什么是Web缓存器(Web Cache)

定义:

Web 缓存器是一种临时存储网页资源(如 HTML、图片、CSS、JS、API 响应等)的系统,用于在后续请求时直接提供这些资源,而不必重新从源服务器获取。

它是浏览器和服务器之间的“中间层”,用来减少重复下载。

Web缓存的常见类型

类型 位置 举例 说明
浏览器缓存(Browser Cache) 客户端 Chrome、Edge、Safari 用户本地保存静态资源(HTML、JS、CSS、图片)
代理缓存(Proxy Cache) 网络中间层 企业代理服务器、CDN 节点 多个用户共享缓存内容
网关缓存(Gateway Cache/反向代理) 靠近服务器 Nginx、Varnish、Cloudflare 替服务器缓存响应,减轻源服务器压力
CDN缓存 全球分布 Cloudflare、Akamai、腾讯云 CDN 将资源缓存到边缘节点,用户就近访问

Web缓存的核心工作机制

当浏览器发出请求时,缓存器会进行如下逻辑:

  1. 检查缓存是否存在

    • 如果命中缓存(Cache Hit)且仍在有效期内 → 直接返回;
    • 否则(Cache Miss)→ 向服务器请求。
  2. 服务器响应时可能附带缓存控制头:

    1
    2
    3
    Cache-Control: max-age=3600, public
    ETag: "abc123"
    Last-Modified: Wed, 10 Jan 2024 10:00:00 GMT
  3. 缓存器根据这些头判断:

    • 资源能否缓存;
    • 缓存有效期;
    • 是否可共享给多个用户;
    • 过期后是否能通过条件请求验证。

HTTP 中与缓存相关的关键首部

首部字段 作用
Cache-Control 指定缓存策略,如 max-ageno-cachepublicprivate
Expires 指定资源过期时间(HTTP/1.0 旧字段)
ETag 资源内容标识(可用于校验是否变更)
Last-Modified 资源最后修改时间
If-None-Match 客户端带上上次的 ETag 请求校验
If-Modified-Since 客户端带上上次修改时间请求校验

Web缓存的优点

优点 说明
提升访问速度 用户可从本地或附近的缓存节点直接获取资源,响应更快。
减少服务器负载 大量重复请求可由缓存处理,服务器压力降低。
节省带宽 不重复下载相同资源,尤其是图片、JS、CSS 等大文件。
提高可用性 源服务器短暂不可用时,缓存仍可提供旧内容(称为 stale content)。
提升用户体验 页面加载速度更快,尤其在移动端和高延迟网络中。

Web缓存的缺点/潜在问题

缺点 说明
数据可能不新鲜(过期) 缓存内容未及时更新时,用户可能看到旧数据。
缓存一致性难题 当服务器更新资源后,如何通知缓存器刷新是复杂问题。
隐私与安全风险 若公共缓存(如代理)缓存了私密响应,可能导致泄露。
开发调试不便 开发阶段缓存常导致“改了代码但浏览器还在用旧文件”的问题。
动态内容难缓存 用户定制化、实时变化的数据往往不能缓存。

Web缓存的两种失效策略

策略 描述 举例
强缓存(Fresh Cache) 在有效期内直接使用,不访问服务器 Cache-Control: max-age=3600
协商缓存(Conditional Cache) 到期后带验证信息向服务器确认是否更新 ETag / If-None-Match 验证

工作流程示意:

1
2
3
4
5
浏览器缓存中命中资源
├── 未过期 → 直接使用(强缓存)
└── 已过期 → 发条件请求(条件GET)
├── 服务器返回 304 Not Modified → 使用本地副本
└── 服务器返回新资源 → 更新缓存

现实应用举例

场景 使用的缓存类型 说明
浏览器打开网页 浏览器缓存 静态资源(图片、JS、CSS)本地缓存
企业内网访问外部网页 代理缓存 所有人共享缓存,提高整体访问速度
大型网站(YouTube、Bilibili) CDN 缓存 + 反向代理缓存 视频内容分布式缓存,减少回源流量

总结

分类 优点 缺点
性能 加快访问速度、减少延迟 数据可能不新鲜
资源利用 降低服务器负载、节省带宽 缓存失效管理复杂
安全性 提供容错能力 不当缓存可能泄露私密信息
适用性 适合静态内容 不适合高动态内容

HTTP和版本区别以及HTTP与HTTPS

HTTP协议的特点

特点 描述 备注
无状态 (Stateless) 服务器不存储关于客户端的任何信息。每一次请求都是独立的,服务器不知道上一次请求是谁发的。 为了保持用户的状态(如登录、购物车),通常需要利用 CookieSessionToken 等机制。
灵活可扩展 HTTP头部字段定义灵活,允许添加新的头部字段来增强功能和语义。 这是它能不断发展和演进的基础。
基于 TCP/IP HTTP 默认使用 TCP 连接进行数据传输,确保传输的可靠性。
明文传输 HTTP/1.x 和 HTTP/2 默认都是明文传输,内容容易被嗅探。 HTTPS 是在 HTTP 上加入了 SSL/TLS 加密层,解决安全问题。
请求-响应模型 严格的交互模式:客户端发起请求,服务器处理并返回响应。

HTTP协议版本对比(进化史)

HTTP 经历了多个版本的迭代,主要是为了解决性能和效率问题。

  1. HTTP/0.9 (原始版本)
  • 特点: 极其简单,只有一个请求方法 GET。只支持传输纯文本,不支持头部和状态码。
  • 用途: 实验性质,已废弃。
  1. HTTP/1.0 (第一个正式版本)
  • 特点: 引入了头部(Headers)状态码多媒体文件类型的支持。
  • 连接模型: 默认使用非持久连接(Non-persistent Connection)
    • 每发起一个请求,客户端都需要与服务器建立一个新的 TCP 连接。请求完成后,连接立即关闭。
    • 问题: 效率低下,频繁建立/断开连接(三次握手/四次挥手)带来了巨大的开销。
  1. HTTP/1.1 (长期主导版本)
  • 特点: 解决了 HTTP/1.0 的性能瓶颈,是使用时间最长、最普及的版本。
  • 核心改进:
    • 持久连接(Persistent Connection): 默认开启。在一次 TCP 连接上,可以发送多个请求和接收多个响应。
    • 管线化(Pipelining): 客户端可以不等上一个响应返回,就发送下一个请求。(实践中应用不多,有队头阻塞问题)
    • 引入 Host 头部: 允许同一台服务器托管多个域名(虚拟主机)。
  • 主要性能瓶颈: 队头阻塞(Head-of-Line Blocking, HOL)。虽然管线化允许并发发送请求,但服务器必须按请求的顺序返回响应。如果第一个请求处理耗时,会阻塞后面所有请求的响应,导致带宽利用率不高。
  1. HTTP/2 (性能飞跃)
  • 特点: 彻底解决了 HTTP/1.1 的队头阻塞问题,是基于 Google SPDY 协议开发的。
  • 核心改进:
    • 二进制分帧(Binary Framing): 将报文拆分成二进制的帧,在传输层上实现并发。
    • 多路复用(Multiplexing):一个 TCP 连接上,同时处理多个请求和响应,并且请求和响应之间互不干扰。彻底消除了 HTTP/1.1 的队头阻塞。
    • 头部压缩(Header Compression): 使用 HPACK 算法压缩请求/响应头部,减小传输数据量。
    • 服务器推送(Server Push): 服务器可以主动推送客户端可能需要的资源(如 CSS/JS 文件),提前加载,无需客户端请求。
  • 部署: 多数浏览器只支持基于 HTTPS 的 HTTP/2 部署,这意味着它默认是加密的。
  1. HTTP/3 (基于 UDP 的创新)
  • 特点: 最大的变化是不再使用 TCP 协议,而是基于 QUIC (Quick UDP Internet Connections) 协议
  • 核心改进:
    • 解决 TCP 队头阻塞: 虽然 HTTP/2 解决了应用层的队头阻塞,但 TCP 协议本身在丢包重传时仍可能导致 TCP 级别的队头阻塞。HTTP/3(QUIC)在应用层实现自己的可靠传输,解决了这个问题。
    • 更快的连接建立: QUIC 协议集成了 TLS 握手,通常只需1个RTT(Round Trip Time)甚至 0 个 RTT 即可完成连接建立和加密握手,比 TCP 的三次握手+TLS 握手快得多。
    • 连接迁移: 当客户端网络环境变化(如 Wi-Fi 切换到 4G),底层 IP 地址变化时,HTTP/2 需要重新建立 TCP 连接。QUIC 通过 Connection ID 机制,可以保持连接不断,实现无缝切换
  • 部署: 尽管协议新,但主流浏览器和 CDN 服务商已经广泛支持。

HTTP与HTTPS

HTTPS 并非是HTTP的复数形式(滑稽),而是 HTTP + SSL/TLS 协议的组合。

特点 HTTP HTTPS
安全性 明文传输,容易被窃听或篡改。 加密传输,数据安全可靠
端口 默认端口:80 默认端口:443
证书 不需要证书 需要 SSL/TLS 证书来验证服务器身份和实现加密
层级 应用层 应用层 + 表示层(加密层)