目录
一、HTTP协议
(一)HTTP请求
1、构建请求
2、HTTP请求发送
3、HTTP 返回的构建
(二)HTTP 2.0
(三)QUIC 协议
1、QUIC协议机制一:自定义连接
2、QUIC协议机制二:自定义重传
3、QUIC协议机制三:无阻塞多路复用
4、QUIC协议机制四:自定义流量控制
二、HTTPS协议
(一)对称加密和非对称加密
(二)HTTPS的工作模式
(三)重放和篡改
三、流媒体协议
(一)常见名词介绍
名词系列一
名词系列二
名词系列三
(二)视频和图片压缩
构建请求之前,需要先将域名发送给 DNS 服务器,解析出目标 IP 地址,然后与目标建立连接。
目前使用的 HTTP 协议大部分都是 1.1。在 1.1 的协议里面,默认是开启了 Keep-Alive 的,这样建立的 TCP 连接,就可以在多次请求中复用。
建立了连接以后,浏览器就要发送 HTTP 的请求了。
HTTP 的报文大概分为三大部分。第一部分是请求行,第二部分是请求的首部,第三部分才是请求的正文实体。
(1)请求行
版本指HTTP版本
方法有以下几种:
(2)首部字段
位于请求行下面。首部是 key value,通过冒号分隔。往往用来保存一些非常重要的字段,例如,Accept-Charset(客户端可以接受的字符集)、Content-Type (正文格式)、Cache-control (控制缓存)——当客户端发送的请求中包含 max-age 指令时,如果判定缓存层中,资源的缓存时间数值比指定时间的数值小,那么客户端可以接受缓存的资源;当指定 max-age 值为 0,那么缓存层通常需要将请求转发给应用集群。If-Modified-Since (也是一个关于缓存的)——如果服务器的资源在某个时间之后更新了,那么客户端就应该下载最新的资源;如果没有更新,服务端会返回“304 Not Modified”的响应,那客户端就不用下载了,也会节省带宽。
使用缓存是因为一个非常大的页面有很多东西。譬如浏览一个商品的详情,里面有这个商品的价格、库存、展示图片、使用手册等等。商品的展示图片会保持较长时间不变,而库存会根据用户购买的情况经常改变。如果图片非常大,而库存数非常小,如果我们每次要更新数据的时候都要刷新整个页面,对于服务器的压力就会很大。
于这种高并发场景下的系统,在真正的业务逻辑之前,都需要有个接入层,将这些静态资源的请求拦在最外面。架构图如下:
对于静态资源,有 Vanish 缓存层,Vanish 是一个 http 反向代理的缓存。 它从客户端接收请求然后尝试从缓存中获取数据来响应客户端的请求,如果 varnish 不能从缓存中获得数据来响应客户端,它将转发请求到后端 (backend servers),获取响应同时存储,最后交付给客户端。当缓存过期的时候,才会访问真正的 Tomcat 应用集群。
HTTP 协议是基于 TCP 协议的,所以它使用面向连接的方式发送请求,通过 stream 二进制流的方式传给对方。到了 TCP 层,它会把二进制流变成一个个报文段发送给服务器。
在发送给每个报文段的时候,都需要对方有一个回应 ACK,来保证报文可靠地到达了对方。如果没有回应,那么 TCP 这一层会进行重新传输,直到可以到达。同一个包有可能被传了好多次,但是 HTTP 这一层不需要知道这一点,因为是 TCP在埋头苦干。
TCP 层发送每一个报文的时候,都需要加上自己的地址(即源地址)和它想要去的地方(即目标地址),将这两个信息放到 IP 头里面,交给 IP 层进行传输。IP 层需要查看目标地址和自己是否是在同一个局域网。如果是,就发送 ARP 协议来请求这个目标地址对应的 MAC 地址,然后将源 MAC 和目标 MAC 放入 MAC 头,发送出去即可;如果不在同一个局域网,就需要发送到网关,还要需要发送 ARP 协议,来获取网关的 MAC 地址,然后将源 MAC 和网关 MAC 放入 MAC 头,发送出去。
网关收到包发现 MAC 符合,取出目标 IP 地址,根据路由协议找到下一跳的路由器,获取下一跳路由器的 MAC 地址,将包发给下一跳路由器。这样路由器一跳一跳终于到达目标的局域网。这个时候,最后一跳的路由器能够发现,目标地址就在自己的某一个出口的局域网上。于是,在这个局域网上发送 ARP,获得这个目标地址的 MAC 地址,将包发出去。
目标的机器发现 MAC 地址符合,就将包收起来;发现 IP 地址符合,根据 IP 头中协议项,知道自己上一层是 TCP 协议,于是解析 TCP 的头,里面有序列号,需要看一看这个序列包是不是它需要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。
TCP 头里面还有端口号,HTTP 的服务器正在监听这个端口号。于是,目标机器就知道是 HTTP 服务器这个进程想要这个包,于是将包发给 HTTP 服务器。HTTP 服务器的进程看到,原来这个请求是要访问一个网页,于是就把这个网页发给客户端。
HTTP 的返回报文也是有一定格式的。这也是基于 HTTP 1.1 的。
状态码会反映 HTTP 请求的结果:“200”意味着大吉大利;“404”也就是“服务端无法响应这个请求”短语会大概说一下原因。
接下来是返回首部的 key value。
这里面,Retry-After 表示,告诉客户端应该在多长时间以后再次尝试一下。
“503 错误”是说“服务暂时不再和这个值配合使用”。在返回的头部里面也会有 Content-Type,表示返回的是 HTML,还是 JSON。
构造好了返回的 HTTP 报文,接下来就是把这个报文发送出去。还是交给 Socket 去发送,还是交给 TCP 层,让 TCP 层将返回的 HTML,也分成一个个小的段,并且保证每个段都可靠到达。这些段加上 TCP 头后会交给 IP 层,然后把刚才的发送过程反向走一遍。虽然两次不一定走相同的路径,但是逻辑过程是一样的,一直到达客户端。
客户端发现 MAC 地址符合、IP 地址符合,于是就会交给 TCP 层。根据序列号看是不是自己要的报文段,如果是,则会根据 TCP 头中的端口号,发给相应的进程。这个进程就是浏览器,浏览器作为客户端也在监听某个端口。当浏览器拿到了 HTTP 的报文。发现返回“200”,一切正常,于是就从正文中将 HTML 拿出来。HTML 是一个标准的网页格式。浏览器只要根据这个格式,展示出一个绚丽多彩的网页。这就是一个正常的 HTTP 请求和返回的完整过程。
HTTP1.1 基础上有了 HTTP 2.0。
HTTP 1.1 在应用层以纯文本的形式进行通信。每次通信都要带完整的 HTTP 的头,而且不考虑 pipeline 模式(管道模式,也称流水线模式。 通过预先设定好的一系列的阶段来处理输入的数据,每个阶段的输出即是下一个阶段的输入)的话,每次的过程总是像上面描述的那样一去一回。这样在实时性、并发性上都存在问题。
为了解决这些问题,HTTP 2.0 对 HTTP 的头进行一定的压缩,将原来每次都要携带的大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引。
另外,HTTP 2.0 协议将一个 TCP 的连接,切分成多个流,每个流都有自己的 ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。它其实只是一个虚拟的通道。流是有优先级的。
HTTP 2.0 还将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。常见的帧有 Header 帧,用于传输 Header 内容,并且会开启一个新的流。再就是 Data 帧,用来传输正文实体。多个 Data 帧属于同一个流。
通过这两种机制,HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。
HTTP 2.0 成功解决了 HTTP 1.1 的队首阻塞问题,同时,也不需要通过 HTTP 1.x 的 pipeline 机制用多条 TCP 连接来实现并行请求与响应;减少了 TCP 连接数对服务器性能的影响,同时将页面的多个数据 css、js、 jpg 等通过一个数据链接进行传输,能够加快页面组件的传输速度。
HTTP 2.0 也是基于 TCP 协议的,TCP 协议在处理包时是有严格顺序的。当其中一个数据包遇到问题,TCP 连接需要等待这个包完成重传之后才能继续进行。
虽然 HTTP 2.0 通过多个 stream,使得逻辑上一个 TCP 连接上的并行内容,进行多路数据的传输,然而这中间并没有关联的数据。一前一后,前面 stream 2 的帧没有收到,后面 stream 1 的帧也会因此阻塞。于是,就又到了从 TCP 切换到 UDP,就是 Google 的 QUIC 协议。
一条 TCP 连接是由四元组标识的,分别是源 IP、源端口、目的 IP、目的端口。一旦一个元素发生变化,就需要断开重连。在移动互联情况下,当手机信号不稳定或者在 WIFI 和 移动网络切换时,都会导致重连,重新进行三次握手,造成一定的时延。
这在 TCP 是没有办法的,但是基于 UDP,就可以在 QUIC 自己的逻辑里面维护连接的机制,不再以四元组标识,而是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。
TCP 为了保证可靠性,通过使用序号和应答机制,来解决顺序问题和丢包问题。任何一个序号的包发过去,都要在一定的时间内得到应答,一旦超时,就会重发这个序号的包。超时时间是借助自适应重传算法,通过采样往返时间 RTT 不断调整的。
其实,在 TCP 里面超时的采样存在不准确的问题。例如,发送一个包,序号为 100,发现没有返回,于是再发送一个 100,过一阵返回一个 ACK101。这个时候客户端知道这个包肯定收到了,但是往返时间是多少呢?是 ACK 到达的时间减去后一个 100 发送的时间,还是减去前一个 100 发送的时间呢?
QUIC 也有个序列号,是递增的。任何一个序列号的包只发送一次,下次就要加一了。例如,发送一个包,序号是 100,发现没有返回;再次发送的时候,序号就是 101 了;如果返回的 ACK 100,就是对第一个包的响应。如果返回 ACK 101 就是对第二个包的响应,RTT 计算相对准确。
但是这里有一个问题,就是怎么知道包 100 和包 101 发送的是同样的内容呢?QUIC 定义了一个 offset 概念。QUIC 既然是面向连接的,也就像 TCP 一样,是一个数据流,发送的数据在这个数据流里面有个偏移量 offset,可以通过 offset 查看数据发送到了哪里,这样只要这个 offset 的包没有来,就要重发;如果来了,按照 offset 拼接,还是能够拼成一个流。
有了自定义的连接和重传机制,就可以解决HTTP 2.0 的多路复用问题。
同 HTTP 2.0 一样,同一条 QUIC 连接上可以创建多个 stream,来发送多个 HTTP 请求。但是,QUIC 是基于 UDP 的,一个连接上的多个 stream 之间没有依赖。这样,假如 stream2 丢了一个 UDP 包,后面跟着 stream3 的一个 UDP 包,虽然 stream2 的那个包需要重传,但是 stream3 的包无需等待,直接可以发给用户。
TCP 的流量控制是借助滑动窗口协议进行的。QUIC 的流量控制也是通过 window_update来告诉对端它可以接受的字节数。但是 QUIC 的窗口是适应自己的多路复用机制的,不但在一个连接上控制窗口,还在一个连接中的每个 stream 控制窗口。
在 TCP 协议中,接收端的窗口的起始点是下一个要接收并且 ACK 的包,即便后来的包都到了,放在缓存里面,窗口也不能右移,因为 TCP 的 ACK 机制是基于序列号的累计应答,一旦 ACK 了一个序列号,就说明前面的都到了,只要前面的没到,后面的到了也不能 ACK。这就容易导致后面的包到了,也有可能超时重传,浪费带宽。
QUIC 的 ACK 是基于 offset 的,每个 offset 的包来了,进了缓存,就可以应答,应答后就不会重发,中间的空档会等待到来或者重发即可,而窗口的起始位置为当前收到的最大 offset,从这个 offset 到当前的 stream 所能容纳的最大缓存,是真正的窗口大小。
用 HTTP 协议,看个新闻还没有问题,但是换到更加严肃的场景中,譬如支付,就存在很多的安全风险了。网络包被截获,很容易被利用。
那怎么解决这个问题呢?一般的思路就是加密。
对称加密,加密和解密使用的密钥是相同的,对称加密算法相比非对称加密算法来说,效率要高得多,性能也好,所以交互的场景下多用对称加密。但是它有一个问题,就是密钥在互联网上传输的话,有可能会被截获,导致信息泄露。因此密码只能通过线下传输。
非对称加密,加密使用的密钥和解密使用的密钥是不相同的——一把公开的公钥,另一把是谁都不能给的私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。公钥可以随意传播,只要保存好私钥就好了。最好是信息交换的双方,都有自己的公钥和私钥,防止被盗用信息。
不对称加密的公钥传播有两种:一种是放在一个公网的地址上,让对方下载;另一种是在建立连接的时候,传给对方。
这两种方法都有一个问题,那就是:作为一个普通的网民,无法鉴定公钥是否真实。
这个时候由权威部门颁发的数字证书(Certificate)来协助证明了。
证书里面有公钥、证书的所有者、证书的发布机构和证书的有效期。
生成证书需要发起一个证书请求,然后将这个请求发给一个CA( Certificate Authority)权威机构去认证,权威机构会通过签名算法给证书卡一个章。
证书请求可以通过命令:
openssl req -key cliu8siteprivate.key -new -out cliu8sitecertificate.req
客户端会发送 Client Hello 消息到服务器,以明文传输 TLS 版本信息、加密套件候选列表、压缩算法候选列表等信息。另外,还会有一个随机数,在协商对称密钥的时候使用。
服务端返回Server Hello 消息, 告诉客户端,服务器选择使用的协议版本、加密套件、压缩算法等,还有一个随机数,用于后续的密钥协商。
客户端从自己信任的 CA 仓库中,拿 CA 证书里面的公钥去解密服务端的证书。如果能够成功,则说明服务端是可信的。这个过程中,可能需要不断往上追溯 CA、CA 的 CA、CA 的 CA 的 CA,直到一个授信的 CA。
证书验证完毕之后,觉得这个外卖网站可信,于是客户端计算产生随机数字 Pre-master,发送 Client Key Exchange,用证书中的公钥加密,再发送给服务器,服务器可以通过私钥解密出来。
到目前为止,无论是客户端还是服务器,都有了三个随机数,分别是:自己的、对端的,以及刚生成的 Pre-Master 随机数。通过这三个随机数,可以在客户端和服务器产生相同的对称密钥。
有了对称密钥,客户端发送 Change Cipher Spec,约定与以后与服务端都采用协商的通信密钥和加密算法进行加密通信,然后发送一个 Encrypted Handshake Message,将已经商定好的参数等,采用协商密钥进行加密,发送给服务器用于数据与握手验证。
同样,服务器也可以发送 Change Cipher Spec,同意以后都采用协商的通信密钥和加密算法进行加密通信,并且也发送 Encrypted Handshake Message 的消息尝试通信。
当双方握手结束之后,就可以通过对称密钥进行加密传输了。这个过程除了加密解密之外,其他的过程和 HTTP 是一样的,过程也非常复杂。上面的过程只包含了 HTTPS 的单向认证,也即客户端验证服务端的证书,是大部分的场景,也可以在更加严格安全要求的情况下,启用双向认证,双方互相验证证书。
有了加密和解密,黑客截获了包也打不开,但是它可以发送 N 次。这个往往通过 Timestamp 和 Nonce 随机数联合起来,然后做一个不可逆的签名来保证。
Nonce 随机数保证唯一,或者 Timestamp 和 Nonce 合起来保证唯一,同样的,请求只接受一次,于是服务器多次收到相同的 Timestamp 和 Nonce,则视为无效即可。
如果有人想篡改 Timestamp 和 Nonce,还有签名保证不可篡改性,如果改了用签名算法解出来,就对不上了,可以丢弃了。
AVI、MPEG、RMVB、MP4、MOV、FLV、WebM、WMV、ASF、MKV
AVI:Audio Video Interleaved,音频视频交错格式。AVI文件将音频(语音)和视频(影像)数据包含在一个文件容器中,允许音视频同步回放。类似DVD视频格式,AVI文件支持多个音视频流。AVI信息主要应用在多媒体光盘上,用来保存电视、电影等各种影像信息。
MPEG:Moving Picture Experts Group,本来的含义是指一个研究视频和音频编码标准的小组,现在泛指该小组制定的一系列视频编码标准。
RMVB:Real Media Variable Bit Rate,可变比特率,一种音频视频压缩规范。较上一代RM格式画面要清晰很多,原因是降低了静态画面下的比特率。
MP4:MP4是一套用于音频、视频信息的压缩编码标准
MOV:QuickTime一种音频、视频文件封装,用于存储常用数字媒体类型。
FLV:Flash Video,流媒体。随着Flash MX的推出发展而来的视频格式。形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,不能在网络上很好的使用等问题。
WebM:一个 以 Matroska(即 MKV)容器格式为基础开发的开放、免费的媒体文件格式,里面包括了VP8影片轨和 Ogg Vorbis 音轨,Google将其拥有的VP8视频编码技术以类似BSD授权开源,Ogg Vorbis 本来就是开放格式。 WebM标准的网络视频更加偏向于开源并且是基于HTML5标准的,WebM 项目旨在为对每个人都开放的网络开发高质量、开放的视频格式,其重点是解决视频服务这一核心的网络用户体验。
WMV:Windows Media Video。微软开发的一系列视频编解码和其相关的视频编码格式的统称,微软Windows媒体框架的一部分。在同等视频质量下,WMV格式的文件可以边下载边播放,很适合在网上播放和传输。
ASF:Advanced Systems Format,一种数字容器格式,用来保存WMV的视频编码。
MKV:Matroska多媒体容器(Multimedia Container),是一种开放标准的自由容器和文件格式,是一种多媒体封装格式,能够在一个文件中容纳无限数量的视频、音频、图片或字幕轨道。其目标是作为一种统一格式保存常见的电影、电视节目等多媒体内容。
H.261、 H.262、H.263、H.264、H.265
H.261:1990年ITU-T制定的一个视频编码标准,属于视频编解码器。最初是针对在ISDN上实现电信会议应用特别是面对面的可视电话和视频会议而设计的。实际的编码算法类似于MPEG算法,但不能与后者兼容。H.261在实时编码时比MPEG所占用的CPU运算量少得多,此算法为了优化带宽占用量,引进了在图像质量与运动幅度之间的平衡折中机制,也就是说,剧烈运动的图像比相对静止的图像质量要差。因此这种方法是属于恒定码流可变质量编码而非恒定质量可变码流编码。
H.262:消费类电子视频设备中使用最广泛的视频编码标准。
H.263:视频会议用的低码率视频编码标准
H.264:继MPEG4之后的新一代高度压缩数字视频编解码器标准
H.265:在H.264的基础上使用先进的技术用以改善码流、编码质量、延时和算法复杂度之间的关系,达到最优化设置。提高压缩效率、提高鲁棒性和错误恢复能力、减少实时的时延、减少信道获取时间和随机接入时延、降低复杂度等。
MPEG-1、MPEG-2、MPEG-3、MPEG-4、MPEG-7、MPEG-21
MPEG-1: 第一个官方的视频音频压缩标准,随后在Video CD中被采用,其中的音频压缩的第三级(MPEG-1 Layer 3)简称MP3, 成为比较流行的音频压缩格式。
MPEG-2: 广播质量的视频、音频和传输协议。被用于无线数位电视-ATSC、DVB以及ISDB、数字卫星电视(例如DirecTV)、 数字有线电视信号,以及DVD视频光盘技术中。
MPEG-3: 原本目标是为高解析度电视(HDTV)设计,随后发现MPEG-2已足够HDTV应用,故 MPEG-3的研发便中止。
MPEG-4:2003 年发布的视频压缩标准,主要是扩展MPEG-1、MPEG-2等标准以支援视频/音频物件(video/audio "objects")的编码、3D内容、低位元率编码(low bitrate encoding)和数位版权管理(Digital Rights Management),其中第10部分由ISO/IEC和ITU-T联合发布,称为H.264/MPEG-4 Part 10。参见H.264。
MPEG-7:MPEG-7并不是一个视频压缩标准,它是一个多媒体内容的描述标准。
MPEG-21:MPEG-21是一个正在制定中的标准,它的目标是为未来多媒体的应用提供一个完整的平台。
视频,就是快速播放一连串连续的图片。每一张图片称为一帧。
帧率(Frame rate)是以帧称为单位的 位图图像连续出现在 显示器上的频率(速率)
课程链接:趣谈网络协议_网络协议_网络编程-极客时间