2.应用层
套接字是应用程序进程和运输层协议之间的接口。
运输层协议特性:可靠数据传输,吞吐量,时延,安全性
运输层提供了 TCP 和 UDP 两种运输服务。TCP 是面向连接的,并提供了可靠的数据传输服务。UDP 不是面向连接的,切不提供可靠数据传输服务。
往返时间 RTT(Round-Trip Time),表示一个短分组从客户到服务器再反悔到客户所花费的时间。RTT 包括分组传播时延,排队时延和处理时延。
HTTP
HTTP 基于 TCP,无需关心数据丢失的问题。HTTP 是个无状态协议,并不会保存关于客户的任何信息。(基于 HTTP 可以实现有状态协议,如 Cookie)。HTTP 请求响应时间大概是 2 个 RTT 加服务器传输 HTML 文件的时间,包含 TCP 三次握手和最后返回数据。HTTP 可使用持续连接模式(keep-alive),这样多次 HTTP 请求可以节省 3 次握手的时间。
HTTP GET 请求报文:
GET /somedir/page.html HTTP/1.1 // 1 请求行,request line Host: www.someschool.edu // 2~4 首部行,header line。Host 知名对象所在主机,用于 Web 代理高速缓存 Connection: close // 不使用持续连接(使用则为 keep-alive) User-agent: Mozilla/5.0 // 浏览器类型 Accept-language: fr // 语言 // 再附加一个回车换行符(CR LF)结束
1234567 | GET /somedir/page.html HTTP/1.1 // 1 请求行,request lineHost: www.someschool.edu // 2~4 首部行,header line。Host 知名对象所在主机,用于 Web 代理高速缓存Connection: close // 不使用持续连接(使用则为 keep-alive)User-agent: Mozilla/5.0 // 浏览器类型Accept-language: fr // 语言// 再附加一个回车换行符(CR LF)结束 |
---|
HTTP GET 响应报文:
HTTP/1.1 200 OK // 1 状态行,status line Connection: close // 2~6 首部行,header line Date: Tue, 09 Aug 2011 15:44:04 GMT // 服务器产生并发送改响应报文的日期和时间 Server: Apache/2.2.3 (CentOS) // 服务器类型 Last-Modified: Tue, 09 Aug 2011 15:11:03 GMT // 被发送对象创建或最后修改的时期和时间,用于对象缓存 Content-Length: 6821 // 被发送对象中的字节数 Conent-Type: text/html // 被发送对象类型 // 再附加一个回车换行符(CR LF)结束 header line (data data data data data ...) // 实体体,entity body // 再附加一个回车换行符结束
1234567891011 | HTTP/1.1 200 OK // 1 状态行,status lineConnection: close // 2~6 首部行,header lineDate: Tue, 09 Aug 2011 15:44:04 GMT // 服务器产生并发送改响应报文的日期和时间Server: Apache/2.2.3 (CentOS) // 服务器类型Last-Modified: Tue, 09 Aug 2011 15:11:03 GMT // 被发送对象创建或最后修改的时期和时间,用于对象缓存Content-Length: 6821 // 被发送对象中的字节数Conent-Type: text/html // 被发送对象类型// 再附加一个回车换行符(CR LF)结束 header line(data data data data data ...) // 实体体,entity body// 再附加一个回车换行符结束 |
---|
条件 GET 方法即在 header line 加入 “If-Modified-Since”,来充分利用本机缓存。如果服务器没有更新该对象,则返回 304 Not Modified,且 entity body 为空;若更新对象则返回正常 200 OK,并带有 entity body。
——- 2019.06.01 ——–
FTP
FTP 使用了两个并行的 TCP 连接来传输文件,一个是控制连接(constrol connnection),一个是数据连接(data connection)。
FTP 协议使用一个独立的控制连接,所以也称 FTP 的控制信息是带外(out-of-band)传送的。HTTP 请求/回复和文件是在同一个 TCP 连接中的,所以 HTTP 是带内(in-band)发送控制信息的。
FTP 控制连接是一直保持的,文件传输每次都建立一个新连接。FTP 会保留用户的状态(state),包括账户,当前目录。状态大大限制了 FTP 的同事维持的会话总数。
FTP 和 HTTP 一样都是可读的。
SMTP
SMTP 是电子邮件使用的服务器间传输协议之一,基于 TCP。HTTP 主要是拉协议(pull protocol),即数据请求方发起链接。SMTP 基本上是推协议(push protocol),即数据发送方发起链接。
SMTP 要求每个报文使用 7 比特 ASCII 码格式。
POP3 / IMAP
POP3(Post Office Protocol——Version 3),IMAP(Internet Mail Access Protocol)协议用于从邮件服务器上取回邮件。
POP3 认证(authorization)后,提供 list,retr,dele,quit 四种命令,完成拉取邮件列表,读取,删除,关闭链接等功能。POP3 的客户端通过这几条命令的组合,可以实现“下载并删除”和“下载并保留”两种模式。
IMAP 比 POP3 复杂,但提供了文件目录功能,可以把邮件分类;也允许只获取部分邮件,如只获取邮件头。
DNS
DNS 是一种主机名到 IP 地址转换的目录服务,是应用层协议。
DNS 还提供了主机别名(host aliasing),邮件服务器别名(mail server aliasing),负载分配(load distribution)功能。
- 主机别名(host aliasing):提供一个比原主机名(又称规范主机名,canonical hostname)更好记的别名
- 邮件服务器别名(mail server aliasing):功能同主机别名
- 负载分配(load distribution):IP 地址集合与同一个规范主机名相联系。
DNS 服务器大致分为三种:根 DNS 服务器,顶级域(Top-Level Domain,LTD,com,org 等就是顶级域名) DNS 服务器和权威 DNS 服务器。
根 DNS 服务器:标号 A 到 M,每个根服务器都是一个集群,2011 年秋季一共有 247 个 根服务器。
还有一类 DNS 是本地 DNS 服务器,每个 ISP 都有一台本地 DNS 服务器(也叫默认名字服务器)。主要为了更高的性能。
迭代查询:请求主机会先访问根 DNS 服务器,得到顶级域 DNS 服务器 IP 地址,再访问顶级域 DNS 服务器得到权威 DNS 服务器 IP 地址,最后从权威 DNS 服务器获取查询的域名对应的 IP 地址。
递归查询:请求主机会先访问根 DNS 服务器,根 DNS 服务器询问顶级域 DNS 服务器,顶级域 DNS 服务器询问权威 DNS 服务器,权威 DNS 服务器返回查询的域名对应的 IP 地址,再沿路返回。
实践中,一般从请求主机到本地 DNS 服务器是递归的,其余是迭代的。
DNS 缓存用于改善时延性能并减少 DNS 报文数量。一般由本地 DNS 服务器做缓存。
DNS 记录和报文
DNS 服务器存储了资源记录(Resource Record,RR)来提供主机名到 IP 地址的映射。格式为:(Name,Value,Type,TTL),TTL 为记录的缓存的生存时间。
- TYPE = A 时,NAME 为主机名,VALUE 为 IP 地址
- TYPE = NS 时,NAME 为域,VALUE 为权威 DNS 服务器主机名,用于指向该域应该向哪个 DNS 服务器查询
- TYPE = CNAME 时,NAME 为别名,VALUE 为规范主机名
- TYPE = MX 时,NAME 为邮件服务器别名,VALUE 为规范主机名
DNS 只有查询和回答两种报文。
DNS 报文格式:
id[2] // 用于标识该查询 flag[2] // 包含:查询 or 回答;希望递归;支持递归;等 questionCount[2] // 问题数 responseCount[2] // 回答 RR 数 authorityCount[2] //权威 RR 数 additionalCount[2] // 附加 RR 数 questionRR[questionLen * questionCount] // 查询的名字和类型字段 responseRR[rrLen * responseCount] // 对查询的响应中的 RR authorityRR[rrLen * authorityCount] // 权威服务器记录 additionalRR[rrLen * additionalCount] // 附加信息 questionLen = len(NAME) + len(TYPE) rrLen = len(NAME) + len(TYPE) + len(VALUE)
123456789101112131415 | id[2] // 用于标识该查询flag[2] // 包含:查询 or 回答;希望递归;支持递归;等questionCount[2] // 问题数responseCount[2] // 回答 RR 数authorityCount[2] //权威 RR 数additionalCount[2] // 附加 RR 数 questionRR[questionLen * questionCount] // 查询的名字和类型字段responseRR[rrLen * responseCount] // 对查询的响应中的 RRauthorityRR[rrLen * authorityCount] // 权威服务器记录additionalRR[rrLen * additionalCount] // 附加信息 questionLen = len(NAME) + len(TYPE)rrLen = len(NAME) + len(TYPE) + len(VALUE) |
---|
以前 DNS 服务器中的内容都是静态配置的,直到最近才添加了一个新的 UPDATE 选项,允许通过 DNS 报文对数据库中的内容进行动态添加或者删除。
P2P
BitTorrent 协议是一个非常流行的 P2P 文件共享协议。BitTorrent 设有追踪服务器(tracker),当一个对等方想要加入 P2P 网络时,则向追踪服务器注册自己,并周期性地通知追踪服务器自己仍在网络中。
当一个对等方 Alice 加入 P2P 网络时,追踪器会随机从对等方集合选择一个子集的 IP 地址(如 50 个)返回。Alice 将自行连接这些 IP 地址。连接上后 Alice 会从连接上的对等方中获取文件的块列表,并根据一定策略从各个对等方中同步过来完整的文件内容。
P2P 网络的数据库实现可以是分布式散列表(Distributed Hash Table,DHT),BitTorrent 正是使用了 Kademlia DHT 来产生一个分布式跟踪器。这个数据库会存储一系列的键值对,其中 key 为文件名,value 为存储了该文件的对等方 IP 地址。当新的对等方请求下载某个文件时,数据库可以返回持有该文件对等方 IP 地址子集以供下载。
简单粗暴的办法可以是每个对等方都维护一个完整的 DHT 数据库。但这对存储和同步的压力会很大。一种精确有效的办法是:为每个对等方分配一个 [0, 2^n – 1] 之间的标识符,对每一个文件都进行 hash,hash 的取值范围也是 [0, 2^n – 1]。然后该文件选择临近的标识符对应的对等方来存储。
那么当我们知道一个文件的 hash 值,需要找到最近的对等方时,应该如何寻找呢?遍历显然是不可取的。其中一个解决方案是 DHT 网络将所有节点组织成一个环形网络,一个对等方只和自己的直接后继和直接前任联系。然后增加一些捷径路径,来大大降低请求需要的报文数量。而捷径的数量选择需要严格的数学论证。目前研究可知,捷径数量和报文数量(与经过的对等方成正比)数量均为 O(log N)。
当某个对等方突然离开时,以该对等方为第 N 后继的节点,会用第 N + 1 个后继代替第 N 后继,然后用新的第 N 后继(旧的第 N + 1 后继)的直接后继作为第 N + 1 个后继。