应用层处理具体的应用协议,是互联网协议最多的一层。
网络应用
基本运行方式:
- 运行在端设备上(网络边缘)
- 在网络上实现进程间通信
不需要在网络核心上实现网络应用,因为网络核心并不运行任何用户程序,同时在终端运行意味着更快的更新速度。
网络架构:
- CS架构:客户端——服务端
- P2P架构:端设备互相直接通信
网络中,设备间的通信依赖网络协议。我们需要一个句柄或接口,使进程能够通过网络发送/接收消息。当前,网络通信的主流接口是socket。socket就像门牌,发送时将消息发到门外,发送过程依赖于门另一侧的传输基础设施,在接收过程中将消息传递到套接字。socket接口。
计算机的进程使用端口标识。
明确服务的传输需求:
| 要求 | 特点 |
|---|---|
| 数据完整性 | 部分应用程序需要100%的数据完整传输,另一些可以容忍部分数据丢失 |
| 延迟 | 一些应用程序需要较低的延迟以满足时效性 |
| 吞吐量 | 一些应用程序(如多媒体)需要小吞吐量 |
| 安全性 | 一些应用程序需要加密和数据完整性, |
Web与HTTP
Web是一个网络应用名,HTTP是它所使用的协议。
Web页面包含很多对象,分布式地存储在不同的服务器上。其中包括HTML文件,图像,音视频文件等。在这个系统中,文档和其他资源通过 统一资源标识符(Uniform Resource Identifiers,或 URI,通常为 URL)进行标识和互相链接。用户可以使用浏览器访问Web上的资源。
HTTP是建立在CS架构上的协议,使用TCP传输。
HTTP是无状态的。表现为每个请求都是独立的,服务器无法识别是不是同一个用户发送的多个请求。
两种连接状态
定义 $\text{RTT}$ 为往返时间(Round-Trip Time):一个数据包从客户端发送到服务端再返回客户端所用的时间。
非持久性连接(Non-persistent HTTP):
- TCP连接开启。
- 每个TCP连接上至多发送一个对象。
- TCP连接关闭。

对于请求的每个对象,它的响应时间包括:
- 1个 $\text{RTT}$ 用来初始化TCP连接。
- 1个 $\text{RTT}$ 用来请求HTTP内容。
- 传输请求内容的时间(transmit time)。
因此,非持久性HTTP的响应时间为 $2 \text{RTT} + \text{transmit time}$
持久性连接(Persistent HTTP):
- TCP连接开启。
- 每个TCP连接可以发送多个对象。
- TCP连接关闭。
HTTP流水线
流水线(HTTP Pipelining):HTTP 客户端在未等待前一个请求的响应的情况下,仍可以连续发送多个 HTTP 请求。

对于请求的每个对象,它的响应时间包括:
- 1个 $\text{RTT}$ 用来初始化TCP连接。
- 1个 $\text{RTT}$ 用来请求HTTP内容。
- 传输请求内容的时间(transmit time)。
- 1个 $\text{RTT}$ 用来继续请求和接收对象。
因此,非持久性HTTP的响应时间为 $3 \text{RTT} + \text{transmit time}$
HTTP信息
HTTP信息包含两部分:请求和回复。
HTTP请求
HTTP请求使用ASCII编码。

以下是一个典型的HTTP请求头:
|
|
常见的HTTP请求:
| 请求 | 内容 |
|---|---|
| GET | 请求资源,也可以发送数据给服务器,但没有body |
| POST | 向服务器发送表单数据 |
| HEAD | 只返回报文不返回对象 |
| PUT | 上传文件到服务器的指定目录 |
HTTP响应
|
|
HTTP响应的返回码标识了此次请求的状态信息。
| 状态码 | 信息 | 含义 |
|---|---|---|
| 200 | OK | 响应成功 |
| 301 | Moved Permanently | 请求内容已转移到别处 |
| 400 | Bad Request | 请求有语法错误,无法识别 |
| 404 | Not Found | 请求内容不在该服务器上 |
| 505 | HTTP Version Not Supported | HTTP版本不支持 |
Cookies
由于 HTTP 协议是无状态的,每个请求互相独立,服务器默认情况下无法知道两个请求是否来自同一客户端或用户。Cookie 的引入使得服务器能够跨多个请求“识别”和“记住”用户。
每个cookies包含以下4个部分:
- HTTP响应消息的cookie头。
- 下一个HTTP请求消息中的cookie头。
- 用户主机保存的cookie文件。
- 结束符。

Web缓存
为了提高Web访问效率,可使用Web缓存。用户设置浏览器指向本地的一个区域,每次用户请求HTTP内容时,先在本地Web缓存中查找内容,若命中则直接返回,否则请求源主机的内容。
DNS系统
DNS是由很多分级的域名服务器组成的分布式数据库。DNS解析过程则是由一系列分布式DNS服务器协作完成的。
DNS服务器
| 类别 | 作用 |
|---|---|
| 根域名服务器 | 位于 DNS 解析的最顶端。它们不直接回答关于哪个域名映射到哪个 IP 地址的查询,而是告诉查询者下一步应该询问哪个顶级域名服务器 |
| 顶级域名服务器 | 负责特定的顶级域名(如 .com,.org,.net 等)。它们为下一级的域名(如 example.com)提供有关权威名称服务器的信息 |
| 权威域名服务器 | 这些服务器为特定的域名(如 example.com)提供详细的 DNS 记录信息(例如 A 记录、MX 记录等)。只有权威服务器才能为其负责的域名提供这些信息。大多数组织拥有权威DNS服务器来为他们的域名提供解析服务 |
| 本地域名服务器 | 在本地网络环境中运行的DNS服务器,它为该网络中的设备提供域名解析服务 |
DNS查询过程
迭代查询:请求方会得到一个“指引”,然后自己去问下一层。

递归查询:本地域名服务器只需向 根域名服务器查询一次,后面的几次查询都是递归地在其他几个域名服务器之间进行的。

DNS缓存
只要任何服务器获得了DNS解析结果,就会将其保存在缓存中。下次查询就可以直接在缓存中寻找结果。
DNS中存在一个 $\text{TTL}$ 字段,表示DNS缓存的保存时间。一旦超过这个期限,DNS缓存就会失效,下次查询就需要重新进行迭代或递归查询。
P2P架构
P2P架构的网络模式不需要一个常驻的服务端,任意端设备之间可以直接通信。每个设备都可以向其他设备请求或提供服务。

考虑一个大小为 $F$ 的文件,现在有 $N$ 个设备需要它。每个设备的上传与下载速率分别为 $u_i$ 和 $d_i$。服务端的上传速率为 $u_s$。
若采用CS架构,则服务端发送所有文件副本到客户端用时为 $\displaystyle \frac{NF}{u_s}$,客户端下载文件用时为 $\frac{F}{d_{\min}}$,则总用时为
$$D_{\text{CS}} \geqslant \max \left\{ \frac{NF}{u_s}, \frac{F}{d_{\min}} \right\}$$若采用P2P架构,上传文件副本用时 $\displaystyle \frac{F}{u_s}$,系统共需要下载 $NF$ 大小的数据,取决于系统的总上传能力 $u_s + \sum u_i$。总用时为
$$D_{\text{P2P}} \geqslant \max \left\{ \frac{F}{u_s}, \frac{F}{d_{\min}}, \frac{NF}{u_s + \sum u_i} \right\}$$Socket编程模型
UDP连接
UDP 的创建非常简单,服务端和客户端一样,只需 socket()。服务器若需要接收数据,则调用 bind() 绑定一个固定端口。

TCP连接
服务端:
| 过程 | 函数 | 备注 |
|---|---|---|
| 建立连接 | socket() -> bind() -> listen() -> accept() |
其中 accept() 会为每个新客户端生成一个专用的 socket 用于后续通信 |
| 读写数据 | send() 和 recv() |
由于 TCP 是流式协议,可能需要循环调用 recv() 才能读取完整消息 |
| 关闭连接 | close() 或 shutdown() |
断开连接 |
客户端:
| 过程 | 函数 | 备注 |
|---|---|---|
| 建立连接 | socket() -> connect() |
其中 connect() 会发起三次握手来建立 TCP连接 |
| 读写数据 | send() 和 recv() |
|
| 关闭连接 | close() 或 shutdown() |
