严格来说,不存在所谓的HTTP连接,HTTP是基于TCP连接进行通信的。
TCP概览
TCP是传输层的可靠传输协议,基于网络层的IP协议之上,以段的形式传输数据
报文结构(每行32位)
源端口|目的端口
TCP序号
TCP确认号
首部长度|保留字|URG|ACK|PSH|RST|SYN|FIN|窗口大小
TCP校验和|紧急指针
可选项
TCP性能因素
-
握手时延
-
慢启动
TCP的发送窗口初始化为1,随着通信过程逐渐增大。因此预热后的连接发送数据会快于刚建立的连接。
-
延迟确认
为了提高TCP报文的数据有效率,一般会等待下次报文发送或超时才捎带对上次接收报文的确认,从而减少空报文的发送。
这就导致报文确认被延迟。
-
Nagle算法
为了更大程度的提高TCP报文的数据有效率,Nagle算法会等到凑够数据达到段的最大值后才发送报文。
这就导致报文的发送被延迟。
-
TIME_AWAIT和端口耗尽
HTTP连接
-
Connection首部
Connection是逐条首部:即不应该被转发的首部。它提供了针对该连接的一些说明信息。
使用:
-
携带具体的逐条首部
-
close,表示要关闭连接
-
-
优化
-
并行连接--多条连接
-
持久连接--保持连接不断开,以便后续的复用
-
HTTP1.0+实现
通过在connection首部中添加keep-alive首部进行支持,但默认采用非持久连接,需要显式说明。
缺陷:哑代理盲中继问题
旧版本的代理服务器可能不认识connection首部而直接转发,这就导致客户端认为自己建立的是持久化连接。
客户端再发完第一条消息后,发送第二条消息时将再也无法获取响应。
-
HTTP1.1实现
默认采用持久化连接,仅当受到Connection:close时才关闭连接
-
-
管道化连接--流水线传输
不必等到HTTP响应才发送下一个HTTP请求
非幂等请求(POST)不应该采用管道化连接
-
连接的关闭
-
半关闭和全关闭
TCP连接具有两条通道:输入通道、输出通道。
如果同时关闭两条通道,称为全关闭。如果仅关闭其中一条通道,称为版关闭。
通常,会先关闭输出通道,再关闭输入通道。
关闭输出通道是安全的,这仅仅表示己方不在发送数据。但关闭输入通道是危险的,连接的另一方很有可能存在数据未发送完成。
-
正常关闭
设连接双方分别为C1、C2,C1主动断开连接。
-
正常连接通信阶段:C1=ESTABLISH,C2=ESTABLISH
-
C1主动关闭连接,发送FIN(握手一),进入FIN-WAIT-1
-
C2收到FIN后,响应ACK(握手二),进入CLOSE-WAIT,发送一些剩余数据
-
C1收到ACK后,进入FIN-WAIT-2,并等待C2的FIN
-
C2发送完剩余的数据后通知C1,发送FIN(握手三),进入LAST-ACK
-
C1收到FIN后,发送ACK(握手四),进入TIME-AWAIT阶段。
-
C1等待2MSL(防止阶段6发送的ACK丢失)
-
C2收到C1的ACK,进入CLOSE阶段
-
C2等待2MSL后,进入CLOSE阶段
-
-
连接关闭时机
-
非持久化连接
非持久化连接上只能完成一个HTTP事务,因此事务完成后就断开连接。
-
持久化连接
一般而言,由于持久化连接可能会有多个http事务,仅当收到Connection:close时才认为连接能够断开。
但是,可能存在某些原因导致Connection:close报文丢失而另一方认为连接已关闭,这种情况下如果仍旧等待Connection:close,那么将永久的维持该连接。为了避免这种情况,服务端都会为持久化连接设置最大空闲时间,超出后将主动断开连接。
-
-
连接异常断开
如果某一方无法完成挥手过程,那么一段时间后另一方会强制关闭连接。
如果某一方在关闭连接后再次接收到消息,就会返回RST报文。