网络应用是计算机网络存在的理由,一批早起的网络应用主要有电子邮件、远程访问、文件传输等,但是随着计算机网络的发展和人类无穷无尽的需求,越来越多的网络应用被开发出来,例如即时通讯和对等(P2P)文件共享,IP 电话、视频会议等。还有一些多方在线游戏被开发出来如《魔兽世界》等,可以说计算机网络是一切应用演变出来的基础。人要怀有一颗感恩的心,感谢这些前辈的努力,才让我们现在的生活如此丰富多彩。但是我们作为程序员,不仅要能够享受这些成果,还要知道为什么,这样生活才会和谐。
研发网络应用程序的核心是写出能够运行在不同的端系统和通过网络彼此通信的程序。例如,在网络应用程序中,有两个互相通信的不同程序:一个是运行在用户主机上的浏览器程序;另一个是运行在 Web 服务器主机上的 Web 服务器程序。
网络应用程序的体系结构(application architecture)
主要有两种,一种是 客户-服务器体系结构(client-server architecture)
,在客户-服务器体系结构中,有一个持续打开,等待连接的主机称为服务器
,它服务于来自许多其他称为 客户
的主机请求。比如 Web 服务器总会等待来自浏览器(运行在客户主机上)的请求。注意这种客户-服务器体系结构中,客户之间是不会彼此交流信息的,它们只与相应的服务器进行通信。还有一点是服务器具有固定的 IP 地址。下图显示了这种体系结构
这种客户-服务器体系结构存在弊端,那就是有的时候服务器的响应跟不上客户请求速度的情况,鉴于此,这种体系结构需要经常配备数据中心(data center)
用来创建更强大的服务器。例如搜索引擎(谷歌、Bing和百度)
、互联网商店(亚马逊、e-Bay 和阿里巴巴)
、基于 Web 的电子邮件(Gmail 和 雅虎)
、社交网络(脸书、Instagram、推特和微信)
,就是用了多个数据中心。
另外一种体系结构是 P2P体系结构(P2P architecture)
,相对于对数据中心有过多依赖的客户-服务器体系结构,P2P 体系结构则直接通过两台相连的主机直接通信,这些主机称为对等方
。典型的 P2P 体系结构的应用包括 文件共享(BitTorrent)
、下载器(迅雷)
、互联网电话和视频会议(Skype)
,下图显示了 P2P 体系结构图
P2P 体系结构最重要的一个特性就是它的自扩展性(self-scalability)
。例如,在一个 P2P 文件共享的应用中,尽管每个对等方都由于请求文件产生工作负载,但每个对等方通过向其他对等方分发文件也为系统增加服务器能力。
我们上面说到了两种体系结构,一种是客户-服务器模式,一种是P2P 对等模式。我们都知道一个计算机允许同时运行多个应用程序,在我们看起来这些应用程序好像是同时运行的,那么它们之间是如何通信的呢?不可能存在同是一个母亲,兄弟俩不交流的情况吧。
用操作系统的术语来说,进行通信实际上是 进程(process)
而不是程序。一个进程可以被认为是运行在端系统中的程序。当多个进程运行在相同的端系统上,它们使用进程间的通信机制相互通信。进程间的通信规则由操作系统来确定。我们暂不关心运行在同一主机上不同应用程序是如何通信的,我们主要探讨的目标是不同端系统中两个进程是如何通信的。还是分为两种结构来探讨。
网络应用程序由成对的进程
组成,这些进程通过网络相互发送报文。例如,在 Web 应用程序中,文件从一个对等方中的进程传输到另一个对等方中的进程。而在每对通信的进程中,都会有一对客户(client)
和 服务器(server)
存在。比如我们上面提到的 Web ,对于 Web 来说,浏览器是一个客户进程,而 Web 服务器是一台服务器进程。也许你也应该能猜到,在 P2P 体系结构中,一个进程能够扮演两种角色,既是客户又是服务器的情况。但是在实际通信的过程中,我们还是很容易区分的,我们通常通过下面这种方式进行区分。
在一对进程之间的通信会话场景中,发起通信(即在会话开始时发起与其他进程的联系)的进程称为
客户
,在会话开始时等待联系的被称为服务器
。
计算机是庞大且繁杂的,计算机网络也是,应用程序不可能只有一个进程组成,它同样是多个进程共同作用协商运行,然而,分布在多个端系统之间的进程是如何进行通信的呢?实际上,每个进程之间会有一个 套接字(socket)
的软件接口存在,套接字是应用程序的内部接口,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将 I/O 插入到网络中,并与网络中的其他应用程序进行通信。
通过一个实例来简单类比一下套接字和网络进程:进程可类比一座房子,而它的套接字相当于是房子的门,当一个进程想要与其他进程进行通信时,它会把报文推出门外,然后通过运输设备把报文运输到另外一座房子,通过门进入房子内部使用。
下图是一个通过套接字进行通信的流程图
从图可以看到,Socket 属于主机或者服务进程的内部接口,由应用程序开发人员进行控制,两台端系统之间进行通信会通过 TCP 的缓冲区经由网络传输到另一个端系统的 TCP 缓冲区,Socket 从 TCP 缓冲区读取报文供应用程序内部使用。
套接字是建立网络应用程序的可编程接口,因此套接字也被称为应用程序和网络之间的 应用程序编程接口(Application Programming Interface,API)
。应用程序开发人员可以控制套接字内部细节,但是无法控制运输层的传输,只能对运输层的传输协议进行选择,还可以对运输层的传输参数进行选择,比如最大缓存和最大报文长度等。
我们上面提到网络应用程序之间会相互发送报文,那么你怎么知道你应该向哪里发送报文呢?是不是存在某种机制能够让你知道你能够发到哪里?这就好比你要发送电子邮件,你写好了内容但是你不知道发发往哪里,所以这个时候必须要有一种知道对方地址的机制,这种机制能够辨明对方唯一的一个地址,这种地址就是 IP地址
。我们会在后面的文章中详细讨论 IP 地址的内容,目前只需要知道 IP 是一个32比特的量并且能够唯一标示互联网中任意一台主机的地址就可以了。
只知道 IP 地址是否就可以了呢?我们知道一台计算机可能回运行多个网络应用程序,那么如何确定是哪个网络应用程序接受发送过来的报文呢?所以这时候还需要知道网络应用程序的 端口号(port number)
。例如, Web 应用程序需要用 80 端口来标示,邮件服务器程序需要使用 25 来标示。
我们知道应用程序是属于互联网四层协议的 应用层
协议,并且四层协议必须彼此协助共同完成工作。好了,这时候我们只有应用层协议,我们需要发送报文,我们如何发送报文呢?这就好比你知道目的地是哪里了,你该如何到达目的地呢?是走路,公交,地铁还是打车?
应用程序发送报文的交通工具
的选择也有很多,我们可以从 数据传输是否可靠、吞吐量、定时和安全性 来考虑,下面是你需要考虑的具体内容。
数据传输是否可靠
我们之前探讨过,分组在计算机网络中会存在丢包问题,丢包问题的严重性跟网络应用程序的性质有关,如果像是电子邮件、文件传输、远程主机、Web 文档传输的过程中出现问题,数据丢失可能会造成非常严重的后果。如果像是网络游戏,多人视频会议造成的影响可能比较小。鉴于此,数据传输的可靠性也是首先需要考虑的问题。因此,如果一个协议提供了这样的确保数据交付的服务,就认为提供了 可靠数据传输(reliable data transfer)
,能够忍受数据丢失的应用被称为 容忍丢失的应用(loss-tolerant application)
。
吞吐量
在之前的文章中我们引入了吞吐量的概念,吞吐量就是在网络应用中数据传输过程中,发送进程能够向接收进程交付比特的速率。具有吞吐量要求的应用程序被称为 带宽敏感的应用(bandwidth-sensitive application)
。带宽敏感的应用具有特定的吞吐量要求,而 弹性应用(elastic application)
能够根据当时可用的带宽或多或少地利用可供使用的吞吐量。
定时
定时是什么意思?定时能够确保网络中两个应用程序的收发是否能够在指定的时间内完成,这也是应用程序选择运输服务需要考虑的一个因素,这听起来很自然,你网络应用发送和接收数据包肯定要加以时间的概念,比如在游戏中,你一包数据迟迟发送不过去,对面都推塔了你还卡在半路上呢。
安全性
最后,选择运输协议一定要能够为应用程序提供一种或多种安全性服务。
说完运输服务的选型,接下来该聊一聊因特网能够提供哪些服务了。实际上,因特网为应用程序提供了两种运输层的协议,即 UDP
和 TCP
,下面是一些网络应用的选择要求,可以根据需要来选择适合的运输层协议。
应用 | 数据丢失 | 带宽 | 时间敏感 |
---|---|---|---|
文件传输 | 不能丢失 | 弹性 | 不敏感 |
电子邮件 | 不能丢失 | 弹性 | 不敏感 |
Web 文档 | 不能丢失 | 弹性 | 不敏感 |
因特网电话/视频会议 | 容忍丢失 | 弹性 | 敏感,100ms |
流式存储音频/视频 | 容忍丢失 | 弹性 | 敏感,几秒 |
交互式游戏 | 容忍丢失 | 弹性 | 是,100ms |
智能手机消息 | 不能丢失 | 弹性 | 无所谓 |
下面我们就来聊一聊这两种运输协议的应用场景
TCP
服务模型的特性主要有下面几种
在应用层数据报发送后, TCP 让客户端和服务器互相交换运输层控制信息。这个握手过程就是提醒客户端和服务器需要准备好接受数据报。握手阶段后,一个 TCP 连接(TCP Connection)
就建立了。这是一条全双工的连接,即连接双方的进程都可以在此连接上同时进行收发报文。当应用程序结束报文发送后,必须拆除连接。
通信进程能够依靠 TCP,无差错、按适当顺序交付所有发送的数据。应用程序能够依靠 TCP 将相同的字节流交付给接收方的套接字,没有字节的丢失和冗余。
TCP 的拥塞控制并不一定为通信进程带来直接好处,但能为因特网带来整体好处。当接收方和发送方之间的网络出现拥塞时,TCP 的拥塞控制会抑制发送进程(客户端或服务器),我们会在后面具体探讨拥塞控制
UDP
是一种轻量级的运输协议,它仅提供最小服务。UDP 是无连接的,因此在两个进程通信前没有握手过程。UDP 也不会保证报文是否传输到服务端,它就像是一个撒手掌柜。不仅如此,到达接收进程的报文也可能是乱序到达的。
下面是上表列出来的一些应用所选择的协议
应用 | 应用层协议 | 支撑的运输协议 |
---|---|---|
电子邮件 | SMTP | TCP |
远程终端访问 | Telnet | TCP |
Web | HTTP | TCP |
文件传输 | FTP | TCP |
流式多媒体 | HTTP | TCP |
因特网电话 | SIP、RTP | TCP或UDP |
现在我们会探讨一些应用层协议,首先来认识一下什么是 应用层协议,应用层协议(application-layer protocol)
定义了运行在不同端系统上的应用进程如何相互传递报文。
应用层协议会定义
域名系统(Domain Name System, DNS)
:用于实现网络设备名字到 IP 地址映射的网络服务。文件传输协议(File Transfer Protocol,FTP)
:用于实现交互式文件传输功能。邮件传送协议(Simple Mail Transfer Protocol, SMTP)
:用于实现电子邮箱传送功能。超文本传输协议(HyperText Transfer Protocol,HTTP)
:用于实现 Web 服务。远程登录协议(Telnet)
:用于实现远程登录功能。Web(World Wide Web)即全球广域网
,也就是 URL 为 www 开头的网络,它是 HTTP 协议的主要载体,是建立在 Internet 上的一种网络服务,我们一般讲的 Web ,其实就是指的 HTTP 协议,HTTP 协议作为 web 程序员必须要掌握并理解的一门协议,有必要好好了解一下。
超文本传输协议可以进行文字分割:超文本(Hypertext)、传输(Transfer)、协议(Protocol),它们之间的关系如下
按照范围的大小 协议 > 传输 > 超文本。下面就分别对这三个名次做一个解释。
在互联网早期的时候,我们输入的信息只能保存在本地,无法和其他电脑进行交互。我们保存的信息通常都以文本
即简单字符的形式存在,文本是一种能够被计算机解析的有意义的二进制数据包。而随着互联网的高速发展,两台电脑之间能够进行数据的传输后,人们不满足只能在两台电脑之间传输文字,还想要传输图片、音频、视频,甚至点击文字或图片能够进行超链接
的跳转,那么文本的语义就被扩大了,这种语义扩大后的文本就被称为超文本(Hypertext)
。
那么我们上面说到,两台计算机之间会形成互联关系进行通信,我们存储的超文本会被解析成为二进制数据包,由传输载体(例如同轴电缆,电话线,光缆)负责把二进制数据包由计算机终端传输到另一个终端的过程(对终端的详细解释可以参考 你说你懂互联网,那这些你知道么?这篇文章)称为传输(transfer)
。
通常我们把传输数据包的一方称为请求方
,把接到二进制数据包的一方称为应答方
。请求方和应答方可以进行互换,请求方也可以作为应答方接受数据,应答方也可以作为请求方请求数据,它们之间的关系如下
如图所示,A 和 B 是两个不同的端系统,它们之间可以作为信息交换的载体存在,刚开始的时候是 A 作为请求方请求与 B 交换信息,B 作为响应的一方提供信息;随着时间的推移,B 也可以作为请求方请求 A 交换信息,那么 A 也可以作为响应方响应 B 请求的信息。
协议这个名词不仅局限于互联网范畴,也体现在日常生活中,比如情侣双方约定好在哪个地点吃饭,这个约定也是一种协议
,比如你应聘成功了,企业会和你签订劳动合同,这种双方的雇佣关系也是一种 协议
。注意自己一个人对自己的约定不能成为协议,协议的前提条件必须是多人约定。
那么网络协议是什么呢?
网络协议就是网络中(包括互联网)传递、管理信息的一些规范。如同人与人之间相互交流是需要遵循一定的规矩一样,计算机之间的相互通信需要共同遵守一定的规则,这些规则就称为网络协议。
没有网络协议的互联网是混乱的,就和人类社会一样,人不能想怎么样就怎么样,你的行为约束是受到法律的约束的;那么互联网中的端系统也不能自己想发什么发什么,也是需要受到通信协议约束的。
那么我们就可以总结一下,什么是 HTTP?可以用下面这个经典的总结回答一下: HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范
HTTP 是可以使用持久性连接和非持久性连接的,下面我们着重探讨一下这两种方式
我们首先来探讨一下持久性连接的 HTTP
你是不是很好奇,当你在浏览器中输入网址后,到底发生了什么事情?你想要的内容是如何展现出来的?让我们通过一个例子来探讨一下,我们假设访问的 URL 地址为 http://www.someSchool.edu/someDepartment/home.index
,当我们输入网址并点击回车时,浏览器内部会进行如下操作
www.someSchool.edu
所在的地址,然后 HTTP 客户端进程在 80 端口发起一个到服务器 www.someSchool.edu
的 TCP 连接(80 端口是 HTTP 的默认端口)。在客户和服务器进程中都会有一个套接字
与其相连。someDepartment/home.index
的资源,我们后面会详细讨论 HTTP 请求报文。存储器(RAM 或磁盘)
中检索出对象 www.someSchool.edu/someDepartment/home.index,然后把检索出来的对象进行封装,封装到 HTTP 响应报文中,并通过套接字向客户进行发送。至此,键入网址再按下回车的全过程就结束了。上述过程描述的是一种简单的请求-响应
全过程,真实的请求-响应情况可能要比上面描述的过程复杂很多。
上面的步骤举例说明了非持久性连接的使用,其中每个 TCP 链接都在服务器发送完成后关闭。每个 TCP 连接只传输一个请求报文和响应报文。
非持久性连接有一些缺点。第一,必须为每个请求的对象建立和维护一个全新的连接。对于每个这样的连接来说,在客户端和服务器中都要分配 TCP 的缓冲区和保持 TCP 变量,这给 Web 服务器带来了严重的负担。因为一台 Web 服务器可能要同时服务于数百甚至上千个客户请求。
在采用 HTTP 1.1 持续连接的情况下,服务器在发送响应后保持该 TCP 连接打开不关闭。在相同的客户与服务器之间,后续的请求和响应报文能够通过相同的连接进行传送。一般来说,如果一跳连接经过一定的时间间隔(可配置)后仍未使用,HTTP 服务器就应该关闭其连接。
我们上面描述了一下 HTTP 的请求响应过程,流程比较简单,但是凡事就怕认真,你这一认真,就能拓展出很多东西,比如 HTTP 报文是什么样的,它的组成格式是什么? 下面就来探讨一下
HTTP 协议主要由三大部分组成:
起始行(start line)
:描述请求或响应的基本信息;头部字段(header)
:使用 key-value 形式更详细地说明报文;消息正文(entity)
:实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据。其中起始行和头部字段并成为 请求头
或者 响应头
,统称为 Header
;消息正文也叫做实体,称为 body
。HTTP 协议规定每次发送的报文必须要有 Header,但是可以没有 body,也就是说头信息是必须的,实体信息可以没有。而且在 header 和 body 之间必须要有一个空行(CRLF),如果用一幅图来表示一下的话,我觉得应该是下面这样
我们使用上面的那个例子来看一下 http 的请求报文
如图,这是 http://www.someSchool.edu/someDepartment/home.index
请求的请求头,通过观察这个 HTTP 报文我们就能够学到很多东西,首先,我们看到报文是用普通 ASCII
文本书写的,这样保证人能够可以看懂。然后,我们可以看到每一行和下一行之间都会有换行,而且最后一行(请求头部后)再加上一个回车换行符。
每个报文的起始行都是由三个字段组成:方法、URL 字段和 HTTP 版本字段。
HTTP 请求方法一般分为 8 种,它们分别是
GET 获取资源
,GET 方法用来请求访问已被 URI 识别的资源。指定的资源经服务器端解析后返回响应内容。也就是说,如果请求的资源是文本,那就保持原样返回;
POST 传输实体
,虽然 GET 方法也可以传输主体信息,但是便于区分,我们一般不用 GET 传输实体信息,反而使用 POST 传输实体信息,
PUT 传输文件,PUT 方法用来传输文件。就像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求 URI 指定的位置。
但是,鉴于 HTTP 的 PUT 方法自身不带验证机制,任何人都可以上传文件 , 存在安全性问题,因此一般的 W eb 网站不使用该方法。若配合 W eb 应用程序的验证机制,或架构设计采用REST(REpresentational State Transfer,表征状态转移)
标准的同类 Web 网站,就可能会开放使用 PUT 方法。
HEAD 获得响应首部,HEAD 方法和 GET 方法一样,只是不返回报文主体部分。用于确认 URI 的有效性及资源更新的日期时间等。
DELETE 删除文件,DELETE 方法用来删除文件,是与 PUT 相反的方法。DELETE 方法按请求 URI 删除指定的资源。
OPTIONS 询问支持的方法,OPTIONS 方法用来查询针对请求 URI 指定的资源支持的方法。
TRACE 追踪路径,TRACE 方法是让 Web 服务器端将之前的请求通信环回给客户端的方法。
CONNECT 要求用隧道协议连接代理,CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接层)
和 TLS(Transport Layer Security,传输层安全)
协议把通信内容加 密后经网络隧道传输。
我们一般最常用的方法也就是 GET 方法和 POST 方法,其他方法暂时了解即可。下面是 HTTP1.0 和 HTTP1.1 支持的方法清单
HTTP 协议使用 URI 定位互联网上的资源。正是因为 URI 的特定功能,在互联网上任意位置的资源都能访问到。URL 带有请求对象的标识符。在上面的例子中,浏览器正在请求对象 /somedir/page.html
的资源。
我们再通过一个完整的域名解析一下 URL
比如 http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument
这个 URL 比较繁琐了吧,你把这个 URL 搞懂了其他的 URL 也就不成问题了。
首先出场的是 http
http://
告诉浏览器使用何种协议。对于大部分 Web 资源,通常使用 HTTP 协议或其安全版本,HTTPS 协议。另外,浏览器也知道如何处理其他协议。例如, mailto:
协议指示浏览器打开邮件客户端;ftp:
协议指示浏览器处理文件传输。
第二个出场的是 主机
www.example.com
既是一个域名,也代表管理该域名的机构。它指示了需要向网络上的哪一台主机发起请求。当然,也可以直接向主机的 IP address 地址发起请求。但直接使用 IP 地址的场景并不常见。
第三个出场的是 端口
我们前面说到,两个主机之间要发起 TCP 连接需要两个条件,主机 + 端口。它表示用于访问 Web 服务器上资源的入口。如果访问的该 Web 服务器使用HTTP协议的标准端口(HTTP为80,HTTPS为443)授予对其资源的访问权限,则通常省略此部分。否则端口就是 URI 必须的部分。
上面是请求 URL 所必须包含的部分,下面就是 URL 具体请求资源路径
第四个出场的是 路径
/path/to/myfile.html
是 Web 服务器上资源的路径。以端口后面的第一个 /
开始,到 ?
号之前结束,中间的 每一个/
都代表了层级(上下级)关系。这个 URL 的请求资源是一个 html 页面。
紧跟着路径后面的是 查询参数
?key1=value1&key2=value2
是提供给 Web 服务器的额外参数。如果是 GET 请求,一般带有请求 URL 参数,如果是 POST 请求,则不会在路径后面直接加参数。这些参数是用 & 符号分隔的键/值对
列表。key1 = value1 是第一对,key2 = value2 是第二对参数
紧跟着参数的是锚点
#SomewhereInTheDocument
是资源本身的某一部分的一个锚点。锚点代表资源内的一种“书签”,它给予浏览器显示位于该“加书签”点的内容的指示。 例如,在HTML文档上,浏览器将滚动到定义锚点的那个点上;在视频或音频文档上,浏览器将转到锚点代表的那个时间。值得注意的是 # 号后面的部分,也称为片段标识符,永远不会与请求一起发送到服务器。
更多有关 HTTP1.1 的内容可以参考博主的这三篇博文,我感觉已经把 HTTP 讲清楚了
看完这篇HTTP,跟面试官扯皮就没问题了
你还在为 HTTP 的这些概念头疼吗?
震惊 | HTTP 在疫情期间把我吓得不敢出门了
自从有了因特网,电子邮件就在因特网上流行起来。与普通邮件一样,电子邮件是一种异步通信媒介,即人们方便的情况下就可以和他人进行邮件往来,而不必与他人进行沟通后在发送。现代电子邮件具有许多强大的特性,包括具有附件、超链接、HTML 格式文本和图片的报文。下面是电子邮件系统的总体概览
从图中我们可以看到它有三个主要组成部分:用户代理(user agent)
、邮件服务器(mail server)
、和简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)
。下面我们就来描述一下邮件收发的过程。
用户代理允许用户阅读、回复、转发、保存和撰写报文。微软的 Outlook
和 Apple Mail
是电子邮件用户代理的例子。当用户编写完邮件时,他的用户代理向邮件服务器发送邮件,此时用户发送的邮件会放在邮件服务器的外出消息队列(Outgoing message queue)
中,当接收方用户想要阅读邮件时,他的用户代理直接从外出消息队列中去取得该报文。
邮件服务器构成了整个邮件系统的核心。每个接收方在其中的邮件服务器上会有一个邮箱(mailbox)
存在。用户的邮箱管理和维护发送给他的报文。一个典型的邮件发送过程是:从发送方的用户代理开始,传输到发送方的邮件服务器,再传输到接收方的邮件服务器,然后在这里被分发到接收方的邮箱中。用接收方的用户想要从邮箱中读取邮件时,他的邮件服务器会对用户进行认证。如果发送方发送的邮件无法正确交付给接收方的服务器,那么发送方的用户代理会把邮件存储在一个报文队列(message queue)
中,并在以后尝试再次发送,通常每30分钟发送一次,如果一段时间后还发送不成功,服务器就会删除报文队列中的邮件并以电子邮件的方式通知发送方。
SMTP
是因特网电子邮件中的主要的应用层协议。SMTP 也使用 TCP 作为运输层协议,保证数据传输的可靠性。
为了描述 SMTP 的基本操作,我们观察一下下面这种常见的情景。
我们假设 Alice 想给 Bob 发送一封简单的 ASCII 报文
运行在 Alice 的邮件服务器上的 SMTP 客户端发现了报文队列中的邮件,它就创建一个到运行在 Bob 邮件服务器上的 SMTP 服务器的 TCP 连接
在经过一些初始化 SMTP 握手后,SMTP 客户端通过该 TCP 连接发送 Alice 的邮件。
在 Bob 想要看邮件时,他会调用用户代理阅读该邮件
上面说的邮件其实就是报文,指的就是一系列 ASCII 码,SMTP 传输邮件之前,需要将二进制多媒体数据编码为 ASCII 码进行传输。
SMTP 一般不使用中间邮件服务器发送邮件,即使这两个邮件服务器位于地球的两端也是这样的。TCP 连接通常直接连接 Alice 的邮件服务器和 Bob 的邮件服务器。
现在你知道了两台邮件服务器邮件发送的大体过程,那么,SMTP 是如何将邮件从 Alice 邮件服务器发送到 Bob 的邮件服务器的呢?主要分为下面三个阶段
建立连接
:在这一阶段,SMTP 客户请求与服务器的25端口建立一个 TCP 连接。一旦连接建立,SMTP 服务器和客户就开始相互通告自己的域名,同时确认对方的域名。邮件传送
:一旦连接建立后,就开始邮件传输。SMTP 依靠 TCP 能够将邮件准确无误地传输到接收方的邮件服务器中。SMTP 客户将邮件的源地址、目的地址和邮件的具体内容传递给 SMTP 服务器,SMTP 服务器进行相应的响应并接收邮件。连接释放
:SMTP 客户发出退出命令,服务器在处理命令后进行响应,随后关闭 TCP 连接。下面我们分析一个实际的 SMTP 邮件发送过程,以下统称为SMTP客户(C)
和 SMTP服务器(S)
。客户的主机名为 crepes.fr
,服务器的主机名为 hamburger.edu
。以 C: 开头的 ASCII 码文本就是客户交给 TCP 套接字的那些行,以 S: 开头的 ASCII 码则是服务器发送给其 TCP 套接字的那些行。一旦创建了连接,就开始了如下过程
S: 220 hamburger.edu
C: HELO crepes.fr
S: 250 Hello crepes.fr, pleased to meet you
C: MAIL FROM:
S: 250 [email protected] ... Sender ok
C: RCPT TO:
S: 250 [email protected] ... Recipient ok
C: DATA
S: 354 Enter mail, end with "." on a line by itself
C: Do you like ketchup?
C: How about pickles?
C: .
S: 250 Message accepted for delivery
C: QUIT
S: 221 hamburger.edu closing connection
在上述例子中,客户从邮件服务器 crepes.fr 向邮件服务器 hamburger.edu 发送了一个报文 (" Do you like ketchup? How about pickles? ") 。作为对话的一部分,该客户发送了 5 条命令: HELO(是 HELLO 的缩写)
、 MAMIL FROM
、RCPT TO
、DATA
以及 QUIT
。这些命令都是自解释的。
什么是自解释,就是不需要再进行解释了,命令自己就能解释自己所要表述的功能。
上面是一个简单的 SMTP 交换过程,包括了连接建立、邮件传送和连接释放三个具体过程
首先建立 TCP 连接、SMTP 调用 TCP 协议的25号端口监听连接请求,然后客户端发送 HELO 指令用来表明自己是发送方的身份,然后服务端作出响应。然后,客户端发送 MAIL FROM 命令,表明客户端的邮件地址是
,服务器以 OK 作为响应,表明准备接收。客户端发送 RCPT TO 表明接收方的电子邮件地址,可以有多个 RCPT 行,即一份邮件可以同时发送给多个收件人。服务器端则表示是否愿意为收件人接收邮件。协商结束后,客户端用 DATA 命令发送信息,结束标志是CRLF.CRLF
,也就是 回车换行.回车换行。最后,控制交互的任一端可选择终止会话,为此它发出一个 QUIT 命令,另一端用命令221响应,表示同意终止连接,双方将关闭连接。
上述过程中会涉及几个类似 HTTP 的状态码。250 就表示 OK ,类似 HTTP 的 200。在命令成功时,服务器返回代码250,如果失败则返回代码550(命令无法识别)、451(处理时出错)、452(存储空间不够)、421(服务器不可用)等,354则表示开始信息输入。
SMTP 的报文会有局限性,SMTP 的局限性表现在只能发送 ASCII 码格式的报文,不支持中文、法文、德文等,它也不支持语音、视频的数据。通过 MIME协议
,对 SMTP 补充。MIME 使用网络虚拟终端(NVT)标准,允许非ASCII码数据通过SMTP传输。
HTTP 是我们学习的第一个应用层协议,SMTP 是我们学习的第二个应用层协议,那么我们就对这两个协议进行比对。
这两个协议都用于从一台主机向另一台主机传送文件:HTTP 从 Web 服务器向 Web 客户端(通常是浏览器)传送文件,SMTP 是从一个邮件服务器向另一个邮件服务器传送文件(即电子邮件报文)。
这两个协议也会有几个重要的区别
拉协议(pull protocol)
,客户端发送请求,请求获取服务端的资源,然后服务端进行响应,把需要下载的文件传输给客户端;而 SMTP 是一个 推协议(push protocol)
,SMTP 的客户端会主动把邮件推送给 SMTP 的服务端。试想一个问题,我们人类可以有多少种识别自己的方式?可以通过身份证来识别,可以通过社保卡号来识别,也可以通过驾驶证来识别,尽管我们有多种识别方式,但在特定的环境下,某种识别方法可能比另一种方法更为适合。因特网上的主机和人类一样,可以使用多种识别方式进行标识。互联网上主机的一种标识方法是使用它的 主机名(hostname)
,如 www.facebook.com、 www.google.com 等。但是这是我们人类的记忆方式,路由器不会这么理解,路由器喜欢定长的、有层次结构的 IP地址
,so,还记得 IP 是什么吗?
IP 地址现在简单表述一下,就是一个由 4 字节组成,并有着严格的层次结构。例如 121.7.106.83
这样一个 IP 地址,其中的每个字节都可以用 .
进行分割,表示了 0 - 255
的十进制数字。(具体的 IP 我们会在后面讨论)
然而,路由器喜欢的是 IP 地址进行解析,我们人类却便于记忆的是网址,那么路由器如何把 IP 地址解析为我们熟悉的网址地址呢?这时候就需要 DNS
出现了。
DNS 的全称是 Domain Name System,DNS
,它是一个由分层的 DNS 服务器(DNS server)
实现的分布式数据库;它还是一个使得主机能够查询分布式数据库的应用层协议。DNS 服务器通常是运行 BIND(Berkeley Internet Name Domain)
软件的 UNIX 机器。DNS 协议运行在 UDP
之上,使用 53 端口。
与 HTTP、FTP 和 SMTP 一样,DNS 协议也是应用层的协议,DNS 使用客户-服务器
模式运行在通信的端系统之间,在通信的端系统之间通过下面的端到端运输协议来传送 DNS 报文。但是 DNS 不是一个直接和用户打交道的应用。DNS 是为因特网上的用户应用程序以及其他软件提供一种核心功能。
DNS 通常不是一门独立的协议,它通常为其他应用层协议所使用,这些协议包括 HTTP、SMTP 和 FTP,将用户提供的主机名解析为 IP 地址。
下面根据一个示例来描述一下这个 DNS 解析过程,这个和你输入网址后,浏览器做了什么操作有异曲同工之处
你在浏览器键入 www.someschool.edu/index.html 时会发生什么现象?为了使用户主机能够将一个 HTTP 请求报文发送到 Web 服务器 www.someschool.edu ,会经历如下操作
除了提供 IP 地址到主机名的转换,DNS 还提供了下面几种重要的服务
主机别名(host aliasing)
,有着复杂的主机名的主机能够拥有一个或多个其他别名,比如说一台名为 relay1.west-coast.enterprise.com 的主机,同时会拥有 enterprise.com 和 www.enterprise.com 的两个主机别名,在这种情况下,relay1.west-coast.enterprise.com 也称为 规范主机名
,而主机别名要比规范主机名更加容易记忆。应用程序可以调用 DNS 来获得主机别名对应的规范主机名以及主机的 IP地址。邮件服务器别名(mail server aliasing)
,同样的,电子邮件的应用程序也可以调用 DNS 对提供的主机名进行解析。负载分配(load distribution)
,DNS 也用于冗余的服务器之间进行负载分配。繁忙的站点例如 cnn.com
被冗余分布在多台服务器上,每台服务器运行在不同的端系统之间,每个都有着不同的 IP 地址。由于这些冗余的 Web 服务器,一个 IP 地址集合因此与同一个规范主机名联系。DNS 数据库中存储着这些 IP 地址的集合。由于客户端每次都会发起 HTTP 请求,所以 DNS 就会在所有这些冗余的 Web 服务器之间循环分配了负载。DNS 是一个复杂的系统,我们在这里只是就其运行的主要方面进行学习,下面给出一个 DNS 工作过程的总体概述
假设运行在用户主机上的某些应用程序(如 Web 浏览器或邮件阅读器) 需要将主机名转换为 IP 地址。这些应用程序将调用 DNS 的客户端,并指明需要被转换的主机名。用户主机上的 DNS 收到后,会使用 UDP 通过 53 端口向网络上发送一个 DNS 查询报文,经过一段时间后,用户主机上的 DNS 会收到一个主机名对应的 DNS 回答报文。因此,从用户主机的角度来看,DNS 就像是一个黑盒子,其内部的操作你无法看到。但是实际上,实现 DNS 这个服务的黑盒子非常复杂,它由分布于全球的大量 DNS 服务器以及定义了 DNS 服务器与查询主机通信方式的应用层协议组成。
DNS 最早的一种简单设计只是在因特网上使用一个 DNS 服务器。该服务器会包含所有的映射。这是一种集中式
的设计,这种设计并不适用于当今的互联网,因为互联网有着数量巨大并且持续增长的主机,这种集中式的设计会存在以下几个问题
单点故障(a single point of failure)
,如果 DNS 服务器崩溃,那么整个网络随之瘫痪。通信容量(traaffic volume)
,单个 DNS 服务器不得不处理所有的 DNS 查询,这种查询级别可能是上百万上千万级远距离集中式数据库(distant centralized database)
,单个 DNS 服务器不可能 邻近
所有的用户,假设在美国的 DNS 服务器不可能临近让澳大利亚的查询使用,其中查询请求势必会经过低速和拥堵的链路,造成严重的时延。维护(maintenance)
,维护成本巨大,而且还需要频繁更新。所以 DNS 不可能集中式设计,它完全没有可扩展能力,因此采用分布式设计
,所以这种设计的特点如下
分布式、层次数据库
首先分布式设计首先解决的问题就是 DNS 服务器的扩展性问题,因此 DNS 使用了大量的 DNS 服务器,它们的组织模式一般是层次方式,并且分布在全世界范围内。没有一台 DNS 服务器能够拥有因特网上所有主机的映射。相反,这些映射分布在所有的 DNS 服务器上。
大致来说有三种 DNS 服务器:根 DNS 服务器
、 顶级域(Top-Level Domain, TLD) DNS 服务器
和 权威 DNS 服务器
。这些服务器的层次模型如下图所示
假设现在一个 DNS 客户端想要知道 www.amazon.com 的 IP 地址,那么上面的域名服务器是如何解析的呢?首先,客户端会先根服务器之一进行关联,它将返回顶级域名 com
的 TLD 服务器的 IP 地址。该客户则与这些 TLD 服务器之一联系,它将为 amazon.com 返回权威服务器的 IP 地址。最后,该客户与 amazom.com 权威服务器之一联系,它为 www.amazom.com 返回其 IP 地址。
我们现在来讨论一下上面域名服务器的层次系统
根 DNS 服务器
,有 400 多个根域名服务器遍及全世界,这些根域名服务器由 13 个不同的组织管理。根域名服务器的清单和组织机构可以在 https://root-servers.org/ 中找到,根域名服务器提供 TLD 服务器的 IP 地址。顶级域 DNS 服务器
,对于每个顶级域名比如 com、org、net、edu 和 gov 和所有的国家级域名 uk、fr、ca 和 jp 都有 TLD 服务器或服务器集群。所有的顶级域列表参见 https://tld-list.com/ 。TDL 服务器提供了权威 DNS 服务器的 IP 地址。权威 DNS 服务器
,在因特网上具有公共可访问的主机,如 Web 服务器和邮件服务器,这些主机的组织机构必须提供可供访问的 DNS 记录,这些记录将这些主机的名字映射为 IP 地址。一个组织机构的权威 DNS 服务器收藏了这些 DNS 记录。一般域名服务器的层次结构主要是以上三种,除此之外,还有另一类重要的 DNS 服务器,它是 本地 DNS 服务器(local DNS server)
。严格来说,本地 DNS 服务器并不属于上述层次结构,但是本地 DNS 服务器又是至关重要的。每个 ISP(Internet Service Provider) 比如居民区的 ISP 或者一个机构的 ISP 都有一台本地 DNS 服务器。当主机和 ISP 进行连接时,该 ISP 会提供一台主机的 IP 地址,该主机会具有一台或多台其本地 DNS 服务器的 IP地址。通过访问网络连接,用户能够容易的确定 DNS 服务器的 IP地址。当主机发出 DNS 请求后,该请求被发往本地 DNS 服务器,它起着代理的作用,并将该请求转发到 DNS 服务器层次系统中。
DNS 缓存(DNS caching)
有时也叫做 DNS 解析器缓存,它是由操作系统维护的临时数据库,它包含有最近的网站和其他 Internet 域的访问记录。也就是说, DNS 缓存只是计算机为了满足快速的响应速度而把已加载过的资源缓存起来,再次访问时可以直接快速引用的一项技术和手段。那么 DNS 的缓存是如何工作的呢?
DNS 缓存的工作流程
在浏览器向外部发出请求之前,计算机会拦截每个请求并在 DNS 缓存数据库中查找域名,该数据库包含有最近的域名列表,以及 DNS 首次发出请求时 DNS 为它们计算的地址。
共同实现 DNS 分布式数据库的所有 DNS 服务器存储了资源记录(Resource Record, RR)
,RR 提供了主机名到 IP 地址的映射。每个 DNS 回答报文中会包含一条或多条资源记录。RR 记录用于回复客户端查询。
资源记录是一个包含了下列字段的 4 元组
(Name, Value, Type, TTL)
RR 会有不同的类型,下面是不同类型的 RR 汇总表
DNS RR 类型 | 解释 |
---|---|
A 记录 | IPv4 主机记录,用于将域名映射到 IPv4 地址 |
AAAA 记录 | IPv6 主机记录,用于将域名映射到 IPv6 地址 |
CNAME 记录 | 别名记录,用于映射 DNS 域名的别名 |
MX 记录 | 邮件交换器,用于将 DNS 域名映射到邮件服务器 |
PTR 记录 | 指针,用于反向查找(IP地址到域名解析) |
SRV 记录 | SRV记录,用于映射可用服务。 |
DNS 报文
DNS 有两种报文,一种是查询报文,一种是响应报文,并且这两种报文有着相同的格式,下面是 DNS 的报文格式
下面对报文格式进行解释
前 12 个报文是 首部区域
,也就是说首部区域有 12 个字节,第一个字段(标识符)是一个 16 比特的数,用于标示该查询。这个标识符会被复制到对查询的回答报文中,以便让客户用它来匹配发送的请求和接受到的回答。 标志字段含有若干标志,标志字段表示为 1 比特,它用于指出报文是 0-查询报文还是 1-响应报文。
问题区域
包含着正在进行的查询信息。这个区域包括:1) 名字字段,包含正在被查询的主机名字;2) 类型字段,指出有关该名字的正被询问的问题类型,例如主机地址是与一个名字相关联(类型 A)还是与某个名字的邮件服务器相关联(类型 MX)。权威区域
包含了其他权威服务器的记录附加区域
包含了其他有帮助的记录。
关于具体 DNS 记录的详细介绍我会出一篇文章专门探讨。
我们上面探讨的协议 HTTP、SMTP、DNS 都采用了客户-服务器
模式,这种模式会极大依赖总是打开的基础设施服务器。而 P2P
是客户端与客户端模式,对总是打开的基础设施服务器有最小的依赖。
P2P 的全称是 Peer-to-peer, P2P
,是一种分布式体系结构的计算机网络。在 P2P 体系中,所有的计算机和设备都被称为对等体,他们互相交换工作。对等网络中的每个对等方都等于其他对等方。网络中没有特权对等体,也没有主管理员设备。
从某种意义上说,对等网络是计算机世界中最平等的网络。每个对等方都相等,并且每个对等方具有与其他对等方相同的权利和义务。对等体同时是客户端和服务器。
实际上,对等网络中可用的每个资源都是在对等之间共享的,而无需任何中央服务器。P2P 网络中的共享资源可以是诸如处理器使用率,磁盘存储容量或网络带宽等。
P2P 的主要目标是共享资源并帮助计算机和设备协同工作,提供特定服务或执行特定任务。如前面说到的,P2P 用于共享各种计算资源,例如网络带宽或磁盘存储空间。 但是,对等网络最常见的例子是 Internet 上的文件共享。 对等网络非常适合文件共享,因为它们允许连接到它们计算机等同时接收文件和发送文件。
BitTorrent
是 P2P 使用的主要协议。
P2P 网络具有一些使它们有用的特征
在流式存储视频应用中,最基础的媒体是预先录制的视频例如电影、电视节目、录制好的体育事件或者用户生成的视频。这些预先录制好的视频会放置在服务器上,用户按需向服务器发送请求来观看视频。许多因特网公司现在提供流式视频,这些公司包括 Netflix、YouTube 、亚马逊和优酷等。
视频式一系列的图像,通常会以一种恒定的速率(如每秒 24 或 30 张图像)来展现。一幅未压缩、数字编码的图像由像素阵列组成,其中每个像素又一些比特编码来表示亮度和颜色。视频的一个重要特征是它能够被压缩、因而可用比特率来权衡视频质量。
在 HTTP 流中,视频只是存储在 HTTP 服务器中的一个文件,每个文件有特定的 URL。当用户想要看视频时,客户与服务器创建一个 TCP 连接并发送该 URL 的 HTTP GET 请求。服务器则以底层网络协议和流量条件允许的尽可能快的速率,在一个 HTTP 响应中发送该文件视频。
尽管 HTTP 流在实践中已经得到广泛部署,但是它由严重缺陷,即所有客户接收到相同编码的视频,但是对于客户而言,带宽时动态变化的,在不同的时间,带宽大小有很大不同。这种情况导致了一种新型 HTTP 流的研发,它常常被称为 经 HTTP 的动态适应性流(Dynamic Adaptive Streaming over HTTP, DASH)
。在 DASH 中,视频编码为几个不同的版本,每个版本对应不同的比特率。
DASH 允许客户使用不同的以太网接入速率流失播放具有不同编码速率的视频。使用 3G 连接的客户能够接受一个低比特率的版本,使用光纤能够接受高比特率的版本。
使用 DASH 后,每个视频版本存储在 HTTP 中,每个版本都有一个不同的 URL。HTTP 服务器也会有一个 告示文件(manifest file)
,为每个版本提供了一个 URL 及其比特率。
现如今,许多因特网视频公司日复一日地向数以百万计的用户按需分发每秒数兆比特的流。对于一个因特网视频公司,或许提供流式视频服务最为直接的方法是建立一个单一的超大规模的数据中心。在数据中心内部存储所有视频,然后把视频返回到全世界范围内的客户。这种方式存在三个问题
如果客户远离数据中心,服务器到客户的分组将跨越许多通信链路并可能通过很多 ISP,造成通信延迟
单点问题,如果单一结点故障,这可能是灾难性的。
为了应对向分布于去啊按时接的用户分发巨量视频数据的挑战,几乎所有主要的视频流公司都利用 内容分发网(Content Distribution Network, CDN)
。 CDN 管理分布在多个地理位置上的服务器,在它的服务器上存储视频副本,并且所有试图将每个用户请求定向到一个提供最好用户体验的 CDN 位置。那么服务器如何选址呢?事实上有两种服务器安置原则
深入
,它的主要目标是靠近用户,通过减少端用户和 CDN 集群之间链路和路由器的数量,从而改善了用户感受的时延和吞吐量。邀请做客
,这个原则是通过在少量(例如 10 个)关键位置建造大集群来邀请 ISP 来做客,与深入设计原则相比,邀请做客设计通常产生较低的维护和管理开销。CDN 可以是专用 CDN(private CDN)
, 即它由内容提供商自己所拥有;另一种 CDN 是 第三方 CDN(third-party CDN)
,它代表多个内容提供商分发内容。
上面我们探讨了一下 CDN 的选址过程,那么 CDN 是如何工作的呢?
当用户主机中的一个浏览器指令检索一个特定的视频(由 URL 标识)时,CDN 必须能够截获请求,来进行下面的操作
大多数 CDN 利用 DNS 协议来截获和重定向请求。
下面是 CDN 的具体工作流程
假设一个内容提供商 NetCinema
,雇用了第三方 CDN 公司 KingCDN
来向它的客户分发视频。在 NetCinema 的 Web 网页上,它的每个视频都被指派了一个 URL,该 URL 包括了字符串 video
以及视频本身的标识符。下面要访问 http://video.netcinema.com/6Y7B23V
,它的工作过程如下
http://video.netcinema.com/6Y7B23V
时,该用户主机发送了对于 video.netcinema.com 的 DNS 请求video
。为了将该 DNS 请求移交给 KingCDN,NetCinema 权威 DNS 服务器并不返回一个 IP 地址,而是向 LDNS 返回一个 KingCDN 域的主机名,如 a1105.kingcdn.comGET
请求。如果使用了 DASH,服务器将首先向客户发送具有 URL 列表的告示文件,每个 URL 对应视频的每个版本,并且客户将动态的选择来自不同版本的块。任何 CDN 的部署,其核心是 集群选择策略(cluster selection strategy)
, 即动态的将客户定向到 CDN 中某个服务器集群或数据中心的机制。一种简单的策略是指派客户到 地理上最为临近(geographically closest)
的集群。这种选择策略忽略了时延和可用带宽随因特网路径时间而变化,总是为特定的客户指派相同的集群;还有一种选择策略是 实时测量(real-time measurement)
,该机制是基于集群和客户之间的时延和丢包性能执行周期性检查。
文章参考
《计算机网络-自顶向下方法》
https://baike.baidu.com/item/应用层协议/3668945?fr=aladdin
https://developer.mozilla.org/en-US/docs/Web/HTTP
https://baike.baidu.com/item/WEB服务器/8390210?fr=aladdin
https://baike.baidu.com/item/内容分发网络/4034265
https://baike.baidu.com/item/HTML/97049?fr=aladdin
https://www.jianshu.com/p/3dd8f1879acb
DNS原理及其解析过程
https://en.wikipedia.org/wiki/Decentralised_system
https://en.wikipedia.org/wiki/Domain_Name_System
https://www.lifewire.com/what-is-a-dns-cache-817514
https://blog.csdn.net/tianxuhong/article/details/74922454
https://www.omnisecu.com/tcpip/what-is-dns-resource-record.php
https://www.digitalcitizen.life/what-is-p2p-peer-to-peer