作者:Gakki
TCP 为什么要三次握手?
- 我们可以从以下几个方面来解释。
- 确认双方的收发能力
- 第一次握手:客户端发送网络包,服务端收到了。服务端得出结论是:客户端的发送能力、服务端的接收能力是正常的。
- 第二次握手:服务端发包,客户端收到了。客户端得出的结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。但此时服务器并不能确认客户端的接收能力是否正常。
- 第三次握手:客户端发包,服务端收到了。服务端得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力正常。
- 因此,只有三次握手才能确认双方的接收与发送能力是否正常。
-
序列号可靠同步
- 如果是两次握手,服务端无法确认客户端是否已经接收到了自己发送的初始序列号,如果第二次握手报文丢失,那么客户端就无法知道服务端的初始序列号,那 TCP 的可靠性就无从谈起。
-
阻止重复历史连接的初始化
- 客户端由于某种原因发送了两个不同序号的 SYN 包,我们知道网络环境是复杂的,旧的数据包有可能先到达服务器。如果是两次握手,服务器收到旧的 SYN 就会立刻建立连接,那么会造成网络异常。
- 如果是三次握手,服务器需要回复 SYN + ACK 包,客户端会对比应答的序号,如果发现是旧的报文,就会给服务器发 RST 报文,直到正常的 SYN 到达服务器后才正常建立连接。
- 所以,三次握手才有足够的上下文信息判断当前连接是否是历史连接。
-
安全问题
- TCP 新建连接时,内核会为连接分配一系列的内存资源,如果采用两次握手就建立连接,那会放大 DDOS 攻击的。
- TCP 作为一种可靠传输控制协议,既要保证数据可靠传输,又要提高传输的效率。所以三次握手就刚好满足上面2个需求。
三次握手可以携带数据吗?
- 第一次、第二次握手不可以携带数据,而第三次握手可以携带数据。
- 如果第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那么他每次都在第一次握手中的 SYN 报文中放入大量的数据,疯狂重复发 SYN 报文,这会让服务器花费许多的内存空间来缓存这些报文。这样会导致服务器更容易被攻击。
- 对于第三次握手,此时客户端已经处于连接状态,他已经知道服务器的接收、发送能力是正常的了。所以携带数据是可以的。
为什么建立连接握手三次,关闭连接时需要是四次呢?
- TCP 在建立连接的时候,客户端发送 SYN + ACK 的包是将 SYN 与 ACK 合并到一个包中,所以减少了一次包的发送,三次完成握手。
- TCP 是全双工通信,在主动关闭方发送 FIN 包后,接收端可能还要发送数据,不能立即关闭服务端到客户端的数据通道,所以也就不能将服务端的 FIN 包与客户端的 ACK 包合并发送,只能先确认 ACK ,然后服务器等没有数据发送时再发送 FIN 包,所以四次挥手必须时四次数据包的交互。
为什么TIME_WAIT 状态需要经过 2MSL 才能返回到 CLOSE 状态?
- MSL :报文在网络中最大生存时间。在客户端发送对服务端的 FIN 的确认包 ACK 后,这个 ACK 包是有可能不可达的,服务端如果收不到 ACK 的话需要重新发送 FIN 包。所以客户端发送 ACK 后需要留出 2MSL 时间( ACK 到达服务器 + 服务器发送 FIN 重传包,一来一回)等待确认服务端确实收到了 ACK 包。也就是说客户端如果等待 2MSL 时间也没有收到服务端重传的 FIN ,那么就可以确认服务端已经收到客户端发送的 ACK 。
另外,在客户端发送完最后一个 ACK 报文段后,在经过 2MSL 时间,就可以使本连接持续的时间内所产生的所有报文都从网络中消失,使下一个新的连接中不会出现旧连接请求报文。
网友评论