网络协议
TCP
协议头
16 位的源端口号/目的端口号
告知目的机器报文段来自哪里(源端口号)以及传给传递给哪个上层协议或者应用程序(目的端口号)。进行 TCP 通讯时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名端口号。在 Linux 系统中,一些知名服务使用的端口号定义在/etc/services 中。
32 位序号
一次 TCP 通讯(从 TCP 连接的建立到断开)整个过程中,一个传输方向上的字节流的每一个报文的编号。
32 位的确认号
用于对对方发来的 TCP 报文段的响应,其值为收到的 TCP 报文段的序号值加 1。
4 位头部长度
标志该 TCP 头部具有多长,单位为字(4 字节),可见 TCP 头部最长为 60 字节。
6 位保留
6 个标志位
① URG: 表示紧急指针是否有效
② ACK: 表示确认号是否有效(携带 ACK 标志的 TCP 报文段称为确认报文段)
③ PSH: 提示接收端应用程序要立即从 TCP 接收缓冲区读走数据,以腾出空间接收后续的数据。(若应用程序不读走数据,数据会一直留在 TCP 模块的接收缓冲区)
④ RST: 表示要求对方重新建立连接(携带 RST 标志的 TCP 报文段为复位报文段)
⑤ SYN: 表示请求建立一个连接(携带 SYN 标志的 TCP 报文段称为同步报文段)
⑥ FIN: 表示通知对方要关闭连接(携带 FIN 标志的 TCP 报文段为结束报文段)
16 位窗口大小
这是 TCP 流量控制的一个手段。此处的窗口指的是接收通告窗口,用于告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
16 位校验和
由发送端填充,接收端对 TCP 报文段执行 CRC 算法以检验 TCP 报文段在传输过程中是否损坏。作为 TCP 可靠传输的重要保障,这个校验不仅包括 TCP 头部,也包括数据部分。
16 位紧急指针
存放着一个正的偏移值,该值加上当前报文的序号将得到紧急指针,紧急指针处存放的是紧急数据,是发送端向接收端发送紧急数据的方法。
TCP 头部选项
TCP 头部选项存放着至多 40 字节的可变长的可选信息(因为 TCP 头部结构最长为 60 字节,除去前面的固定部分)。典型的 TCP 头部选项结构结构如下:
(1) Kind: 说明选项类型
(2) Length: (如果有的话)指定该选项的总长度
(3) Info: (如果有的话)选项的具体信息
可选项信息有如下情况:
(1) Kind=0
选项表结束选项
(2) Kind=1
空操作选项,无特殊意义,一般用于将 TCP 选项的总长度填充为 4 字节的整数倍
(3) Kind=2
最大报文段长度选项,TCP 连接初始化时,通信双方使用此选项来协商最大报文长度(Max Segment Size, MMS)。
(4) Kind=3
窗口扩大因子。TCP 连接初始化时,通信双方使用该选项来协商接收通告窗口的扩大因子。在 TCP 头部中,接收通告窗口大小用 16 位表示,故最大为 65535 字节。实际上 TCP 模块允许的接收通告窗口大小远不止这个数,窗口扩大因子解决了此问题。假设接收通告窗口大小为 N,扩大因子为 M,那么 TCP 报文段的实际接收通告窗口大小为 N 乘 2^M,即 N 左移 M 位。M 的取值范围是 0~14,/proc/sys/net/ipv4/tcp_window_scaling
内核变量用来启用或关闭窗口扩大因子选项。
MSS 选项与窗口扩大因子选项只能出现在同步报文段中,否则将被忽略。但是同步报文段不执行窗口的扩大操作,即同步报文段的接收通告窗口大小就是该 TCP 报文段的实际接收通告窗口大小。当连接建立完毕后,每个数据传输方向的窗口扩大因子就固定不变了。
(5) Kind=4
选择性确认(Selective Acknowledgment, SACK)选项。TCP 通信时若某个 TCP 报文段丢失则 TCP 模块会重传最后被确认的 TCP 报文段后续的所有报文段,这样原先已经正确传输的 TCP 报文段可能会被重复发送,从而降低 TCP 性能。SACK 技术使 TCP 模块只重新发送丢失的 TCP 报文段,不用发送所有未被确认的 TCP 报文段。选择性确认用于连接初始化时表示是否支持 SACK 技术。/proc/sys/net/ipv4/tcp_sack 内核变量用于启动/关闭选择性确认选项。
(6) Kind=5
SACK 实际工作的选项,该选项的参数部分用于告诉发送方本端已收到并缓存的不连续的数据块,从而让发送端可以据此检查并重发丢失的数据块。
(7) Kind=8
时间戳选项,该选项提供了较为准确的计算通信双方之间的回路时间(Round Trip Time, RTT)的方法,从而为 TCP 流量控制提供重要信息。/proc/sys/net/ipv4/tcp_timestamps 内核变量用于启动/关闭时间戳选项
可靠性传输
1、检验和
TCP 检验和的计算与 UDP 一样,在计算时要加上 12byte 的伪首部,检验范围包括 TCP 首部及数据部分,但是 UDP 的检验和字段为可选的,而 TCP 中是必须有的。
2、序列号
TCP 将每个字节的数据都进行了编号,这就是序列号。
序列号的作用:
a、保证可靠性(当接收到的数据总少了某个序号的数据时,能马上知道)
b、保证数据的按序到达
c、提高效率,可实现多次发送,一次确认
d、去除重复数据
数据传输过程中的确认应答处理、重发控制以及重复控制等功能都可以通过序列号来实现
3、确认应答机制(ACK)
TCP 通过确认应答机制实现可靠的数据传输。在 TCP 的首部中有一个标志位——ACK,此标志位表示确认号是否有效。接收方对于按序到达的数据会进行确认,当标志位 ACK=1 时确认首部的确认字段有效。进行确认时,确认字段值表示这个值之前的数据都已经按序到达了。而发送方如果收到了已发送的数据的确认报文,则继续传输下一部分数据;而如果等待了一定时间还没有收到确认报文就会启动重传机制。
4、超时重传机制
当报文发出后在一定的时间内未收到接收方的确认,发送方就会进行重传(通常是在发出报文段后设定一个闹钟,到点了还没有收到应答则进行重传)
当然,未收到确认不一定就是发送的数据包丢了,还可能是确认的 ACK 丢了。
当接收方接收到重复的数据时就将其丢掉,重新发送 ACK。而要识别出重复的数据,就要用到前面提到的序列号了,利用序列号很容易就可以做到去重的效果。
重传时间的确定:报文段发出到收到应答中间有一个报文段的往返时间 RTT,显然超时重传时间 RTO 会略大于这个 RTT,TCP 会根据网络情况动态的计算 RTT,即 RTO 是不断变化的。在 Linux 中,超时以 500ms 为单位进行控制,每次判定超时重发的超时时间都是 500ms 的整数倍。其规律为:如果重发一次仍得不到应答,就等待 2*500ms 后再进行重传,如果仍然得不到应答就等待 4*500ms 后重传,依次类推,以指数形式递增,重传次数累计到一定次数后,TCP 认为网络或对端主机出现异常,就会强行关闭连接。
5、连接管理机制
连接管理机制即 TCP 建立连接时的三次握手和断开连接时的四次挥手。
首先三次握手:
建立过程为:
(1)Server 首先建立传输控制块 TCB,进入 LISTEN(收听)状态,等待用户的连接请求。如有,则建立连接。(这个过程在套接字编程中为服务器端调用 socket 函数、bind 函数和 listen 函数的过程)
(2)Client 建立传输控制块 TCB,然后向 B 发送连接请求报文段,报文段中首部的同步位 SYN=1,同时选择一个序列号 seq=j,TCP 规定 SYN 报文段不携带数据,但要消耗一个序列号。然后 A 进入 SYN-SENT(同步已发送)状态。(这个过程在套接字编程中为客户端调用 socket 函数和 connect 函数的过程)
(3)Server 收到请求后,如同意建立连接,就向 Client 发送确认报文段。此时 SYN=1、ACK=1,确认号 ack=j+1,同时选择一个序列号 seq=k,这个报文也不携带数据,但要消耗一个序列号。然后 B 进入 SYN-RCVD 状态(同步收到)。
(4)Client 收到 Server 的确认后,还要向 Client 发送确认。确认报文段的 ACK=1,确认号 ack=k+1,seq=j+1。TCP 规定,ACK 报文段可以携带数据,而如果不携带数据则不消耗序列号,此时下一个报文段的序列号仍为 seq=j+1。这时,连接就建立成功了,Client 进入 ESTABLISHED 状态(已建立连接状态)。
(5)当 Server 收到 Client 的确认后,也进入 ESTABLISHED 状态,此时就可以进行数据传输了。
当然,在进行三次握手时不是仅进行连接,可能还会进行一些后续操作所需要的信息交流。
四次挥手:
连接的双方都可以提出释放连接,这里假设 Client 先提出释放连接,首先双方都处于 ESTABLISHED 状态。
(1)当 Client 的数据传送完后,就可以向其 TCP 发起连接释放了,此后停止再发送数据,主动关闭 TCP 连接。首先 Client 向 Server 发送一个 FIN 报文段,报文段首部 FIN=1,序列号 seq=m(m 为最后传送的数据的序列号加 1),然后 Client 进入 FIN-WAIT-1(终止等待 1)状态。FIN 报文段不能携带数据,但要消耗一个序列号。
(2)Server 收到释放连接的报文段后即发出确认报文段,报文首部 ACK=1,ack=m+1,seq=n(n 等于 Server 前面传送过的数据的序列号加 1),然后 Server 进入 CLOSE-WAIT(关闭等待)状态。这时 TCP 连接就处于半关闭状态。(注意:此后 Client 不能主动向 Server 发送数据,但是 Client 可以给 Server 发送确认报文段,也就是说 Client 仍要接收来自 Server 的报文)
(3)当 Client 收到 Server 的确认报文后,就进入 FIN-WAIT-2(终止等待 2)状态,等待 Server 发出的连接释放报文段。
(4)当 Server 的数据发送完毕后,其应用进程就通知 TCP 释放连接。Server 向 Client 发送 FIN 报文,报文段首部 FIN=1,ack=m+1(重复发送上一次已经发送过的确认号),seq=k(k 为 Server 最后发送报文段的序列号加 1)。然后 Server 进入 LAST-ACK(最后确认)状态,等待 A 的确认。
(5)Client 在接收到 Server 的连接释放报文后,必须进行确认。Client 向 Server 发送的确认报文段中报文首部 ACK=1,ack=k+1,seq=m+1。然后 Client 进入 TIME-WAIT(时间等待)状态(如果无差错,此状态时间为 2MSL),注意,此时 TCP 连接还没有释放掉,必须经过 TIME-WAIT 设置的时间 2MSL 后,Client 撤销相应的传输控制块 TCB,才进入 CLOSED 状态,结束了此次 TCP 连接。MSL 叫做最长报文段寿命,RFC793 建议设为 2 分钟,但在现在实际网络情况中,常用值有三种:30 秒,1 分钟,2 分钟。必须要在 Client 进入 CLOSED 状态后才能开始建立下一个新的连接。
(6)Server 收到 Client 的确认报文后,也进入 CLOSED 状态,撤销相应的传输控制块 TCB,此时,TCP 连接全部断开。
这样 TCP 四次挥手完成。
为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端。而关闭连接时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即 close,也可以发送一些数据给对方后,再发送 FIN 报文给对方来表示同意现在关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送。
为什么 TIME_WAIT 状态需要经过 2MSL(最大报文段生存时间)才能返回到 CLOSE 状态?
TIME_WAIT 状态就是用来重发可能丢失的 ACK 报文。在 Client 发送出最后的 ACK 回复,但该 ACK 可能丢失。Server 如果没有收到 ACK,将不断重复发送 FIN 片段。所以 Client 不能立即关闭,它必须确认 Server 接收到了该 ACK。Client 会在发送出 ACK 之后进入到 TIME_WAIT 状态。Client 会设置一个计时器,等待 2MSL 的时间。如果在该时间内再次收到 FIN,那么 Client 会重发 ACK 并再次等待 2MSL。
Client 在发送完 ACK 报文段后,再经过 2MSL 时间,就可以使本连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段。
6、流量控制
接收端处理数据的速度是有限的,如果发送方发送数据的速度过快,导致接收端的缓冲区满,而发送方继续发送,就会造成丢包,继而引起丢包重传等一系列连锁反应。
因此 TCP 支持根据接收端的处理能力,来决定发送端的发送速度,这个机制叫做流量控制。
在 TCP 报文段首部中有一个 16 位窗口长度,当接收端接收到发送方的数据后,在应答报文 ACK 中就将自身缓冲区的剩余大小,放入 16 位窗口中。这个大小随数据传输情况而变,窗口越大,网络吞吐量越高,而一旦接收方发现自身的缓冲区快满了,就将窗口设置为更小的值通知发送方。如果缓冲区满,就将窗口置为 0,发送方收到后就不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
其过程如下:
注意:窗口大小不受 16 位窗口大小限制,在 TCP 首部 40 字节选项中还包含一个窗口扩大因子 M,实际窗口大小是窗口字段的值左移 M 位。
7、拥塞控制
拥塞的标志
重传计时器超时
接收到三个重复确认
拥塞控制的机制
慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery )。
慢开始和拥塞避免
发送方维持一个拥塞窗口 cwnd ( congestion window )的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞。
发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。
慢开始算法:当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。因此,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段 MSS 的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个 cwnd 的数值。用这样的方法逐步增大发送方的拥塞窗口 cwnd ,可以使分组注入到网络的速率更加合理。
每经过一个传输轮次,拥塞窗口 cwnd 就加倍。一个传输轮次所经历的时间其实就是往返时间 RTT。不过“传输轮次”更加强调:把拥塞窗口 cwnd 所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认。
另,慢开始的“慢”并不是指 cwnd 的增长速率慢,而是指在 TCP 开始发送报文段时先设置 cwnd=1,使得发送方在开始时只发送一个报文段(目的是试探一下网络的拥塞情况),然后再逐渐增大 cwnd。
为了防止拥塞窗口 cwnd 增长过大引起网络拥塞,还需要设置一个慢开始门限 ssthresh 状态变量(如何设置 ssthresh)。慢开始门限 ssthresh 的用法如下:
当 cwnd < ssthresh 时,使用上述的慢开始算法。
当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。
拥塞避免算法:让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是加倍。这样拥塞窗口 cwnd 按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。
无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢开始门限 ssthresh 设置为出现拥塞时的发送方窗口值的一半(但不能小于 2)。然后把拥塞窗口 cwnd 重新设置为 1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
如下图,用具体数值说明了上述拥塞控制的过程。现在发送窗口的大小和拥塞窗口一样大。
<1>. 当 TCP 连接进行初始化时,把拥塞窗口 cwnd 置为 1。前面已说过,为了便于理解,图中的窗口单位不使用字节而使用报文段的个数。慢开始门限的初始值设置为 16 个报文段,即 cwnd = 16 。
<2>. 在执行慢开始算法时,拥塞窗口 cwnd 的初始值为 1。以后发送方每收到一个对新报文段的确认 ACK,就把拥塞窗口值另 1,然后开始下一轮的传输(图中横坐标为传输轮次)。因此拥塞窗口 cwnd 随着传输轮次按指数规律增长。当拥塞窗口 cwnd 增长到慢开始门限值 ssthresh 时(即当 cwnd=16 时),就改为执行拥塞控制算法,拥塞窗口按线 性规律增长。
<3>. 假定拥塞窗口的数值增长到 24 时,网络出现超时(这很可能就是网络发生拥塞了)。更新后的 ssthresh 值变为 12(即变为出现超时时的拥塞窗口数值 24 的一半),拥塞窗口再重新设置为 1,并执行慢开始算法。当 cwnd=ssthresh=12 时改为执行拥塞避免算法,拥塞窗口按线性规律增长,每经过一个往返时间增加一个 MSS 的大小。
强调:“拥塞避免”并非指完全能够避免了拥塞。利用以上的措施要完全避免网络拥塞还是不可能的。“拥塞避免”是说在拥塞避免阶段将拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞。
快重传和快恢复
如果发送方设置的超时计时器时限已到但还没有收到确认,那么很可能是网络出现了拥塞,致使报文段在网络中的某处被丢弃。这时,TCP 马上把拥塞窗口 cwnd 减小到 1,并执行慢开始算法,同时把慢开始门限值 ssthresh 减半。这是不使用快重传的情况。
快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时才进行捎带确认。
接收方收到了 M1 和 M2 后都分别发出了确认。现在假定接收方没有收到 M3 但接着收到了 M4。
显然,接收方不能确认 M4,因为 M4 是收到的失序报文段。根据可靠传输原理,接收方可以什么都不做,也可以在适当时机发送一次对 M2 的确认。
但按照快重传算法的规定,接收方应及时发送对 M2 的重复确认,这样做可以让发送方及早知道报文段 M3 没有到达接收方。发送方接着发送了 M5 和 M6。接收方收到这两个报文后,也还要再次发出对 M2 的重复确认。这样,发送方共收到了接收方的四个对 M2 的确认,其中后三个都是重复确认。
与快重传配合使用的还有快恢复算法,其过程有以下两个要点:
<1>. 当发送方连续收到三个重复确认,就执行“乘法减小”算法,把慢开始门限 ssthresh 减半。这是为了预防网络发生拥塞。请注意:接下去不执行慢开始算法。
<2>. 由于发送方现在认为网络很可能没有发生拥塞,因此与慢开始不同之处是现在不执行慢开始算法(即拥塞窗口 cwnd 现在不设置为 1),而是把 cwnd 值设置为 慢开始门限 ssthresh 减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大。
下图给出了快重传和快恢复的示意图,并标明了“TCP Reno 版本”。
区别:新的 TCP Reno 版本在快重传之后采用快恢复算法而不是采用慢开始算法。
在采用快恢复算法时,慢开始算法只是在 TCP 连接建立时和网络出现超时时才使用。
接收方根据自己的接收能力设定了接收窗口 rwnd,并把这个窗口值写入 TCP 首部中的窗口字段,传送给发送方。因此,接收窗口又称为通知窗口。因此,从接收方对发送方的流量控制的角度考虑,发送方的发送窗口一定不能超过对方给出的接收窗口 rwnd 。
发送方窗口的上限值 = Min [ rwnd, cwnd ]
当 rwnd < cwnd 时,是接收方的接收能力限制发送方窗口的最大值。
当 cwnd < rwnd 时,则是网络的拥塞限制发送方窗口的最大值。
HTTP
演变历史
https://www.ruanyifeng.com/blog/2016/08/http.html
版本 产生时间 内容 发展现状
HTTP/0.9 1991 年 不涉及数据包传输,规定客户端和服务器之间通信格式,只能 GET 请求 没有作为正式的标准
HTTP/1.0 1996 年 传输内容格式不限制,增加 PUT、PATCH、HEAD、 OPTIONS、DELETE 命令 正式作为标准
HTTP/1.1 1997 年 持久连接(长连接)、节约带宽、HOST 域、管道机制、分块传输编码 2015 年前使用最广泛
HTTP/2 2015 年 多路复用、服务器推送、头信息压缩、二进制协议等 逐渐覆盖市场
主要特点
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。
灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。5、支持 B/S 及 C/S 模式。
请求格式(请求协议)
响应格式(响应协议)
请求方法
根据 HTTP 标准,HTTP 请求可以使用多种请求方法。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。
HTTP1.1 新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
状态码
所有 HTTP 响应的第一行都是状态行,依次是当前 HTTP 版本号,3 位数字组成的状态代码,以及描述状态的短语,彼此由空格分隔。
状态代码的第一个数字代表当前响应的类型:
1xx 消息——请求已被服务器接收,继续处理
2xx 成功——请求已成功被服务器接收、理解、并接受
3xx 重定向——需要后续操作才能完成这一请求
4xx 请求错误——请求含有词法错误或者无法被执行
5xx 服务器错误——服务器在处理某个正确请求时发生错误
虽然 RFC 2616 中已经推荐了描述状态的短语,例如"200 OK","404 Not Found",但是 WEB 开发者仍然能够自行决定采用何种短语,用以显示本地化的状态描述或者自定义信息。
常用请求头
HTTPS
首先看看组成 HTTPS 的协议:HTTP 协议和 SSL/TLS 协议。SSL/TLS 就是负责加密解密等安全处理的模块,所以 HTTPS 的核心在 SSL/TLS 上面。整个通信如下:
1、浏览器发起往服务器的 443 端口发起请求,请求携带了浏览器支持的加密算法和哈希算法。
2、服务器收到请求,选择浏览器支持的加密算法和哈希算法。
3、服务器下将数字证书返回给浏览器,这里的数字证书可以是向某个可靠机构申请的,也可以是自制的。
4、浏览器进入数字证书认证环节,这一部分是浏览器内置的 TLS 完成的:
4.1 首先浏览器会从内置的证书列表中索引,找到服务器下发证书对应的机构,如果没有找到,此时就会提示用户该证书是不是由权威机构颁发,是不可信任的。如果查到了对应的机构,则取出该机构颁发的公钥。
4.2 用机构的证书公钥解密得到证书的内容和证书签名,内容包括网站的网址、网站的公钥、证书的有效期等。浏览器会先验证证书签名的合法性。签名通过后,浏览器验证证书记录的网址是否和当前网址是一致的,不一致会提示用户。如果网址一致会检查证书有效期,证书过期了也会提示用户。这些都通过认证时,浏览器就可以安全使用证书中的网站公钥了。
4.3 浏览器生成一个随机数 R,并使用网站公钥对 R 进行加密。
5、浏览器将加密的 R 传送给服务器。
6、服务器用自己的私钥解密得到 R。
7、服务器以 R 为密钥使用了对称加密算法加密网页内容并传输给浏览器。
8、浏览器以 R 为密钥使用之前约定好的解密算法获取网页内容。
备注 1:前 5 步其实就是 HTTPS 的握手过程,这个过程主要是认证服务端证书(内置的公钥)的合法性。因为非对称加密计算量较大,整个通信过程只会用到一次非对称加密算法(主要是用来保护传输客户端生成的用于对称加密的随机数私钥)。后续内容的加解密都是通过一开始约定好的对称加密算法进行的。
备注 2:SSL/TLS 是 HTTPS 安全性的核心模块,TLS 的前身是 SSL,TLS1.0 就是 SSL3.1,TLS1.1 是 SSL3.2,TLS1.2 则是 SSL3.3。 SSL/TLS 是建立在 TCP 协议之上,因而也是应用层级别的协议。其包括 TLS Record Protocol 和 TLS Handshaking Protocols 两个模块,后者负责握手过程中的身份认证,前者则保证数据传输过程中的完整性和私密性。
WebSocket
简介
WebSocket 本质上一种计算机网络应用层的协议,用来弥补 http 协议在持久通信能力上的不足。
我们知道 http 协议本身是无状态协议,每一个新的 http 请求,只能通过客户端主动发起,通过 建立连接-->传输数据-->断开连接 的方式来传输数据,传送完连接就断开了,也就是这次 http 请求已经完全结束了(虽然 http1.1 增加了 keep-alive 请求头可以通过一条通道请求多次,但本质上还是一样的)。
并且服务器是不能主动给客户端发送数据的(因为之前的请求得到响应后连接就断开了,之后服务器根本不知道谁请求过),客户端也不会知道之前请求的任何信息。
所以说,http 协议本身是没有持久通信能力的,但是我们在实际的应用中,是很需要这种能力的,所以 WebSocket 协议由此而生,于 2011 年被 IETF 定为标准 RFC6455,并被 RFC7936 所补充规范。
并且在 HTML5 标准中增加了有关 WebSocket 协议的相关 api,所以只要实现了 HTML5 标准的客户端,就可以与支持 WebSocket 协议的服务器进行全双工的持久通信了。
这里的持久通信能力指的是协议本身的能力,我们当然可以通过编程的方式实现这种功能,比如轮询的方式。
计算机网络里还有 socket 关键字,这里的 socket 指的是运输层协议的某一端,泛指某个应用程序。
unix 编程里还有一个 socket 接口,这里的译名是套接字,泛指应用层协议的端口号。
原理
与 http 协议一样,WebSocket 协议也需要通过已建立的 TCP 连接来传输数据。具体实现上是通过 http 协议建立通道,然后在此基础上用真正的 WebSocket 协议进行通信,所以 WebSocket 协议和 http 协议是有一定的交叉关系的。
下面是 WebSocket 协议请求头:
其中请求头中重要的字段:
1. Connection 和 Upgrade 字段告诉服务器,客户端发起的是 WebSocket 协议请求
2. Sec-WebSocket-Extensions 表示客户端想要表达的协议级的扩展
3. Sec-WebSocket-Key 是一个 Base64 编码值,由浏览器随机生成
4. Sec-WebSocket-Version 表明客户端所使用的协议版本
而得到的响应头中重要的字段:
1. Connection 和 Upgrade 字段与请求头中的作用相同
2. Sec-WebSocket-Accept 表明服务器接受了客户端的请求
Status Code:101 Switching Protocols
并且 http 请求完成后响应的状态码为 101,表示切换了协议,说明 WebSocket 协议通过 http 协议来建立运输层的 TCP 连接,之后便与 http 协议无关了。
优缺点
优点:
· WebSocket 协议一旦建议后,互相沟通所消耗的请求头是很小的
· 服务器可以向客户端推送消息了
缺点:
· 少部分浏览器不支持,浏览器支持的程度与方式有区别
应用场景
· 即时聊天通信
· 多玩家游戏
· 在线协同编辑/编辑
· 实时数据流的拉取与推送
· 体育/游戏实况
· 实时地图位置
评论