HTTP, Hyper Text Transport Protocol
HTTP 基于 TCP 实现了可靠网络通信,屏蔽了【确保消息的完整性和顺序性等】具体通信细节,为开发者和用户都提供了很大的方便
既然是进行通信,那就意味着信息和资源的传递——【资源】一词意味着相当多种类的内容,从静态的文档、图片、视频,到动态的网络服务——比如我们常用的各种 app ,它们给我们展示的图片和视频是静态资源,根据我们的身份提供专门为我们准备的内容是动态资源
URI, Uniform Resource Identifier
全世界每个被服务器提供的资源都有一个名字,这个名字就是 URI,客户端通过 URI 来定位资源并进行传输。
比如给定这样一个URI:
http://www.gov.cn/govweb/xhtml/2016gov/images/public/logo_wz1.jpg
浏览器就能取回下面这个图片资源:
URI 有两种具体的实现方式,分别是 URL 和 URN。但后者目前基本没有应用实例,所以在很多语境下 URI 等同于 URL (比如上面例子中的链接就是一个 URL )
URL, Uniform Resource Locator
URL 告诉我们该通过什么方式、到哪里获取到我们想要的资源。比如上面的图片的链接http://www.gov.cn/govweb/xhtml/2016gov/images/public/logo_wz1.jpg
。一般来说, URL 都可以分为三个部分来看:
- 第一段是协议名(正式的名字叫 scheme ),就是例子中的
http://
。说明,如果想要这个资源,要使用 http 协议进行连接(当然还有不少其他类型的协议,比如 HTTPS、 FTP 等) - 第二段是 IP 地址,这里是
www.gov.cn
。说明这个资源在域名为 www.gov.cn 的这台服务器(域名通过 DNS 转换为 IP 地址,所以访问网站本质上还是通过 IP 地址进行的) - 第三段是资源名,如
/govweb/xhtml/2016gov/images/public/logo_wz1.jpg
说明了这个图片资源在这台服务器上的什么地方、叫什么名字
绝大多数的 URL 基本都符合下面的格式:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
比如用 bing 搜一个”abc“,那 url 大概就是这样的:https://cn.bing.com/search?q=abc
,内容都可以和上面的格式对上(省略了相当多的字段)。问号?
后面的叫做【Query Strings】,实际上多数的网站都用这个来传递送给服务器的参数供服务器解析,就比如刚刚那个例子。如果有多个参数要传递,则可以用&
连接多个参数。
又比如,请求一个 ftp 也许是这样的:ftp://anonymous:mypwd@ftp.prep.ai.mit.edu/pub/gnu
,内容也都可以和上面的格式对上(同样省略了一些字段)
最后那个 frag 其实是 fragment 的意思,在实际应用上基本都是用来给 html 里面的锚点进行定位的
URN, Uniform Resource Name
URN 就是给特定资源的独一无二的名称,就像一个 ISBN 号标记唯一一本书一样。
博主个人见过的唯一一个实例,是 IPFS 项目——在其系统内部,使用资源的 hash 值作为资源的唯一标记进行访问。由于其采用的 SHA 的空间足够大,所以理论上不存在碰撞问题
这里就不多讨论了
HTTP Message(HTTP 消息)
HTTP 的通信交互都是一问一答的,这 ”问“ 和 ”答“ 就叫做 【HTTP 消息】
HTTP 消息分为 Request 和 Respond,两者均由头部(Headers)和消息正文(Body)组成,如下图所示
请求 Request
格式:
下图是访问百度的一个请求头实例,可以和上面对应着看,应该很容易看懂
- 请求行(Start-line)
- 请求方法(Method,此处仅说一下 GET 和 POST):
- GET:一般不用报文中的请求数据传值,而是直接将参数和 URL 拼在一起,明文写在地址栏中。地址栏中填入的
?
隔开 URL 和请求参数,多个参数用&
隔开。浏览器支持的总长一般不超过 8182 个字符(IE:2083)。对于非 ASCII 字符,经 BASE64 编码发送,值中的%XX
表示 XX 是 ASCII 的 hex 表示 - POST:一般将参数和数据放在报文的【请求数据】中,以 <名称, 值> 对的形式保存,可传大量数据(理论上无限制)
- GET:一般不用报文中的请求数据传值,而是直接将参数和 URL 拼在一起,明文写在地址栏中。地址栏中填入的
- 请求方法(Method,此处仅说一下 GET 和 POST):
- 头部(HTTP Headers):
关键字: 值
对组成,每行一对。请求头部通知服务器有关于客户端请求的信息,下面举几个例子- Authorization:授权信息,常出现在对服务器发送的 WWW-Authenticate 头的应答中
- Content-Length:请求消息正文的长度
- Cookie:可以用来在用户处缓存一些数据(比如用于存储一些状态、进行身份验证等。各浏览器一般限制每个域名存 50 个 cookie,总大小不超过 4MB )
- Content-Type:定义文件类型、网页编码,决定浏览器如何读取该数据。比如某些链接点击后展开空的新页面随即开始下载文件。此处详细内容见下面的 MIME
- Referer:表明该请求来自哪个 URL (比如从一个站点)
- 空行(Empty line):标明 header 的边界
- 请求数据(Body)
- POST 例:对于
user:admin, password:123
,数据为user=admin&password=123
- POST 例:对于
响应 Response
下图是访问百度的一个响应头实例
与请求类似,响应也可以分为四个部分
- 响应头:描述服务器信息、数据信息等
- 响应体:大致可分为三类,可以是已知长度的单个文件(其 body 可由 Content-Type 和 Content-Length 定义)、未知长度的单个文件(通过将 Transfer-Encoding 设置为 chunked 使用 chunks 编码)和由多个body分别存不同信息段的数据组成(少见)
实际上,Header 还可以分类为 Request headers、General headers、Entity headers,如下图所示:
请求报文:
响应报文:
如上图所示,头其实还可以分类为通用头和实体头:
- 通用头:请求、响应均支持的头域
- 实体头:包含实体信息的头。实体信息一般由实体头和实体组成
MIME: Multipurpose Internet Mail Extensions
MIME 类型,标记了【要被传输的数据的类型】,用来表示文档、文件或字节流的性质和格式——比如发送的数据是什么类型(比如文本、图片、音频、视频、代码等)、发送的数据有多大等。
对于什么数据该叫什么名字这件事,是由一个叫做 IANA 的大组织规定的,具体可见:www.iana.org/assignments… 截止本文写作时的2020年10月,大概有2000种不同的标记
Web 服务器和客户端都会对发送的 HTTP 对象附上一个 MIME 类型说明,这样两端在收到数据时,就都可以根据 MIME 类型来决定如何对待收到的数据(比如对纯粹的文本,浏览器就可以直接显示出来。如果是要被下载的文件,就会调起浏览器的文件下载器)
浏览器通常使用MIME类型(而不是文件扩展名)来确定如何处理URL,因此Web服务器在响应头中添加正确的MIME类型非常重要。如果配置不正确,浏览器可能会曲解文件内容,网站将无法正常工作,并且下载的文件也会被错误处理
类型举例:
text/plain
text/html
image/jpeg
video/mp4
【application 意味着是某种二进制数据】
application/json
application/javascript
application/octet-stream 一般的二进制流,如文件下载
【可被用来发包含多段内容的表单,表单里可以含文件,实现上传】
multipart/form-data
HTTP 下面的 Socket
HTTP 是基于 TCP 的,而 TCP 的具体数据传输则要通过 Socket 进行。
Socket ,是用标准 UNIX File Descriptions 与其他程序沟通的方式
首先,浏览器通过 DNS 获取到所请求域名的 IP 地址(若直接对 地址:端口
的端点(Endpoint)进行请求,则跳过此步),然后与端点进行三次握手,建立 TCP Socket:
- 发送端发送连接请求的报文
- 服务端收到请求连接的报文,向发送端返回报文
- 发送端确认收到了正确的服务端报文,再次发送确认报文
接下来进行 TCP 通信,直至需要关闭连接。通常服务器返回结果后就会关闭连接。但若请求中包含 Connection:keep-alive
,则会保持 TCP 连接(也就是【长连接】,HTTP1.1 默认都是长连接了)
HTTPS——“HTTP Over TLS”
HTTPS 就是 HTTP Over TLS,目前用的主要是 TLS1.1 和 TLS1.2
HTTPS 需要提供的特性:
- 客户端和服务器的身份认证:双方都需要有办法验证对方的身份,比如用户不会希望访问一个假的银行网站,银行网站也不会希望允许一个冒牌的用户进行操作
- 保证传输数据的完整性:客户端和服务器通信的内容不能被中间的坏人篡改
- 加密通信:防止通信内容被窃取
- 高效:不能让通信的性能下降太多
目前采用的 HTTPS 方案,直接在 HTTP 下面一层增加了 TLS 协议,安全性由 TLS 保障,而不需要在 HTTP 协议层做太多的修改
主要的修改内容,基本上就是将原本 TCP 上面的输入和输出换成 TLS 的输入和输出,并加入一些新的通信步骤来完成保证安全相关的操作。
后续会另写一篇文章来更详细讲讲 HTTPS 。