三次握手
三次握手过程中涉及到的客户端服务器的状态有:
- CLOSED: 连接已关闭
- LISTEN: 正在监听连接
- SYN-SENT: 已发送连接请求
- SYN-RCVD: 已收到连接请求
- ESTABLISHED: 连接已建立
涉及到的标志位有:
- SYN: 是否已请求建立连接
- ACK: 是否已确认建立连接
涉及到的序列号有:
- seq: 请求连接时的序列号
- ack: 确认连接的确认号,为请求序列号+1
具体过程:
- 客户端处于ClOSED状态,服务端处于LISTEN状态。
- 客户端发送请求连接,携带seq=x,并将SYN置为1,状态更改为SYN-SENT。---
第一次握手
- 服务端确认客户端的请求,即ack=x+1, 并将ACK置为1,同时发送本端的同步请求,seq=y,并将SYN置为1。此时状态更改为SYN-RCVD。---
第二次握手
- 客户端确认服务端的请求,发送ack=y+1, 并将ACK置为1,同时seq=x+1, 此时客户端单方面状态更改为ESTABLISHED。---
第三次握手
- 服务端收到ack,状态更改为ESTABLISHED。
- 双方可以互相发送数据。
为何需要三次,而不是两次或四次?
这个问题的大前提是连接是基于不可靠信道建立的,假如信道完全可靠,那么零次握手也是可以做到正常数据传输的。
所以tcp协议需要做的是在不可靠信道的前提下尽可能保证数据传输的可靠性。
如果是两次,当第二次握手结束后,服务端就认为已经建立了连接,此时假如客户端发送了一次数据,由于网络问题服务端并没有收到,于是客户端超时重传,这次服务端收到了,随后关闭了连接。 但是第一次的数据并没有丢失而是滞留在某个网络节点,此时又到达了服务端,如果是两次握手即可建立连接的话,此时服务端给一个ack+seq就又建立起一次连接,但是事实上此次连接是不需要的,因为客户端没有数据要发送,那么服务端就一直处于等待传输数据或者已传输数据等待回应状态,如果这种类型的客户端在连接后大量出现,那么就会消耗很多服务端资源,甚至导致服务不可用。
如果是四次:没必要。因为永远存在红蓝军问题,不可能做到传输过程的百分之百确认。
其实,总的来说,TCP 需要 seq 序列号来做可靠重传或接收,而避免连接复用时无法分辨出 seq 是延迟或者是旧链接的 seq,因此需要三次握手来约定确定双方的 ISN(初始 seq 序列号)。