计算机网络

应用层

应用层处理具体的应用协议,是互联网协议最多的一层。

网络应用

基本运行方式:

  • 运行在端设备上(网络边缘)
  • 在网络上实现进程间通信

不需要在网络核心上实现网络应用,因为网络核心并不运行任何用户程序,同时在终端运行意味着更快的更新速度。

网络架构:

  • CS架构:客户端——服务端
  • P2P架构:端设备互相直接通信

网络中,设备间的通信依赖网络协议。我们需要一个句柄或接口,使进程能够通过网络发送/接收消息。当前,网络通信的主流接口是socketsocket就像门牌,发送时将消息发到门外,发送过程依赖于门另一侧的传输基础设施,在接收过程中将消息传递到套接字。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):

  1. TCP连接开启。
  2. 每个TCP连接上至多发送一个对象。
  3. TCP连接关闭。

非持久性HTTP

对于请求的每个对象,它的响应时间包括:

  • 1个 $\text{RTT}$ 用来初始化TCP连接。
  • 1个 $\text{RTT}$ 用来请求HTTP内容。
  • 传输请求内容的时间(transmit time)。

因此,非持久性HTTP的响应时间为 $2 \text{RTT} + \text{transmit time}$

持久性连接(Persistent HTTP):

  1. TCP连接开启。
  2. 每个TCP连接可以发送多个对象。
  3. TCP连接关闭。

HTTP流水线

流水线(HTTP Pipelining):HTTP 客户端在未等待前一个请求的响应的情况下,仍可以连续发送多个 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请求头:

1
2
3
4
5
6
7
8
GET /index.html HTTP/1.1\r\n
Host: www-net.cs.umass.edu\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0 \r\n
Accept: text/html,application/xhtml+xml\r\n
Accept-Language: en-us,en;q=0.5\r\n
Accept-Encoding: gzip,deflate\r\n
Connection: keep-alive\r\n
\r\n

常见的HTTP请求:

请求 内容
GET 请求资源,也可以发送数据给服务器,但没有body
POST 向服务器发送表单数据
HEAD 只返回报文不返回对象
PUT 上传文件到服务器的指定目录

HTTP响应

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
HTTP/1.1 200 OK
Date: Tue, 08 Sep 2020 00:53:20 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.9 mod_perl/2.0.11 Perl/v5.16.3
Last-Modified: Tue, 01 Mar 2016 18:57:50 GMT
ETag: "a5b-52d015789ee9e"
Accept-Ranges: bytes
Content-Length: 2651
Content-Type: text/html; charset=UTF-8
\r\n
data data data data data ... 

HTTP响应的返回码标识了此次请求的状态信息。

状态码 信息 含义
200 OK 响应成功
301 Moved Permanently 请求内容已转移到别处
400 Bad Request 请求有语法错误,无法识别
404 Not Found 请求内容不在该服务器上
505 HTTP Version Not Supported HTTP版本不支持

Cookies

由于 HTTP 协议是无状态的,每个请求互相独立,服务器默认情况下无法知道两个请求是否来自同一客户端或用户。Cookie 的引入使得服务器能够跨多个请求“识别”和“记住”用户。

每个cookies包含以下4个部分:

  1. HTTP响应消息的cookie头。
  2. 下一个HTTP请求消息中的cookie头。
  3. 用户主机保存的cookie文件。
  4. 结束符。

含有cookie的HTTP

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架构的网络模式不需要一个常驻的服务端,任意端设备之间可以直接通信。每个设备都可以向其他设备请求或提供服务。

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() 绑定一个固定端口。

UDP的socket交互过程

TCP连接

服务端:

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

客户端:

过程 函数 备注
建立连接 socket() -> connect() 其中 connect() 会发起三次握手来建立 TCP连接
读写数据 send()recv()
关闭连接 close()shutdown()

TCP的socket交互过程

网站总访客数:Loading

使用 Hugo 构建
主题 StackJimmy 设计