三次握手
三次握手流程
- 第一次握手:客户端给服务器发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c),上图中的x。此时客户端处于
SYN_SEND
状态。 - 第二次握手:服务器收到客户端的 SYN 报文,指定自己的初始化序列号 ISN(s),上图中的y。把客户端发送的 ISN 值 + 1,作为返回报文的 ack 值,表示自己已经收到了客户端的 SYN,此时服务器处于
SYN_RCVD
状态。 - 第三次握手:客户端收到服务器发送的 SYN 报文后,会发送一个 ACK 报文,把第二次握手的 ISN值 + 1,作为 ack 值,第三次握手的序列号为第一次的序列号 + 1。此时客户端处于
ESTABLISHED
状态,服务器收到 ACK 报文后,也会处于ESTABLISHED
状态,连接建立。第三次握手可以携带数据。
为什么需要三次握手
- 第一次握手,服务器验证了客户端的发送能力,和服务器的接收能力
- 第二次握手,客户端验证了客户端的发送能力,服务器的接收能力 ,服务器的发送能力
- 第三次握手,在第一次的基础上,服务器又验证了客户端的接收能力和服务器的发送能力
半连接队列 / 全连接对列
在收到客户端的第一次握手后,服务器处于SYN_RCVD
状态,此时双方还没有正式建立连接。服务器会把这中状态的请求连接放到一个队列里,这个队列被称为半连接队列。
已经完成三次握手的连接,会被放在全连接队列中。
ISN(Initial Sequence Number)的值选择
当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号。ISN随时间而变化,因此每个连接都将具有不同的ISN。ISN可以看作是一个32比特的计数器,每4ms加1 。这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。
三次握手的其中一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果 ISN 是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。
为什么 ack 的值要在 syn 的基础上加1
ack 表示数据的偏移量,比如第一次握手时客户端传输的 syn 为 99,服务端返回的 ack 为 100,代表第三次握手时客户端传输的数据从 100 开始。