为什么要三次握手而不是两次?
从全双工这个角度出发,tcp能发能收。
简单来说,三次握手的目的是为了让双方验证各自的接收能力和发送能力。
- 第一次握手,A 发送SYN+seq到B,B接收到了后,能确认什么呢?
显然,B能确认A的发送能力和B的接收能力,确认A的序列号。
- 第二次握手,B发送SYN+ACK+seq+ack到A,A接收到后,能确认什么呢?
A能确认B的发送能力和A自己的接收能力,此外,A收到了SYNACK,那么说明前面A发的SYN成功到达B的手中,所以也能确认A自己的发送能力和B的接收能力;至此,A已经确认了双方各自的发送能力和接收能力都是OK的,因此转为ESTABLISHED状态;确认B的序列号。
- 第三次握手,A发送ACK到B,B接收后,能确认什么呢?
直接的,B能确认A的发送能力和B的接收能力,另外由于B能收到ACK说明前面发送的SYNACK已经成功被接受了,说明能确认A的接收能力和B的发送能力。B确认双方各自的发送能力和接收能力。转为ESTABLISHED状态。
如果采用两次握手,就不能确认上述的四种能力,导致出现问题
假定不采用第三次报文握手,那么只要B发出确认,新的连接就建立了。假定A发出的报文段并没有丢失,而是在某些网络节点中长时间滞留了,以致延误到连接释放后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,却误以为是又发出了一次新的连接请求,于是就向A发出确认报文段,同意建立连接。但是现在A没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据(两次握手过程已经结束,等待A的发送数据),但B却以为新的运输连接已经建立了,并一直在等待A发来的数据,B的资源就浪费了。
客户端正在和服务端建立 TCP 连接,然而当服务器变 SYN-RCVD 后,此时一个旧的 SYN 报文 又到达了,服务器会如何处理?
旧的SYN 连接到达服务器时,服务器照常返回,客户端给服务端发送RST 报文,将服务端重置为LISTEN。
服务端在SYN_RECEIVED状态下,接收到旧的SYN 报文时是不能作出判断的,而是照常返回,当客户端接收到该报文后发现异常,才会发送RST 报文,重置连接。
第三次握手失败了怎么办?

ACK报文丢失导致第三次握手失败
当客户端收到服务端的SYNACK应答后,其状态变为ESTABLISHED,并会发送ACK包给服务端,准备发送数据了。如果此时ACK在网络中丢失(如上图所示),过了超时计时器后,那么服务端会重新发送SYNACK包,重传次数根据/proc/sys/net/ipv4/tcp_synack_retries来指定,默认是5次。如果重传指定次数到了后,仍然未收到ACK应答,那么一段时间后,Server自动关闭这个连接。
问题就在这里,客户端已经认为连接建立,而服务端则可能处在SYN-RCVD或者CLOSED,接下来我们需要考虑这两种情况下服务端的应答:
- 服务端处于CLOSED,当接收到连接已经关闭的请求时,服务端会返回RST 报文,客户端接收到后就会关闭连接,如果需要的话则会重连,那么那就是另一个三次握手了。
服务端处于SYN-RCVD,此时如果接收到正常的ACK 报文,那么很好,连接恢复,继续传输数据;如果接收到写入数据等请求呢?注意了,此时写入数据等请求也是带着ACK 报文的,实际上也能恢复连接,使服务器恢复到ESTABLISHED状态,继续传输数据。
为什么 TIME_WAIT 状态需要经过 2MSL 才能转换到 CLOSE 状态?
第一,为了保证客户端发送的最后一个ACK 报文能够到达服务器。我们必须假设网络是不可靠的,ACK 报文可能丢失。如果服务端发出FIN 报文后没有收到ACK 报文,就会重发FIN 报文,此时处于TIME-WAIT状态的客户端就会重发ACK 报文。当然,客户端也不能无限久的等待这个可能存在的FIN 报文,因为如果服务端正常接收到了ACK 报文后是不会再发FIN 报文的。因此,客户端需要设置一个计时器,那么等待多久最合适呢?所谓的MSL(Maximum Segment Lifetime)指一个报文在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL时间后,客户端都没有再次收到FIN 报文,那么客户端推断ACK 报文已经被服务器成功接收,所以结束TCP 连接。
第二,防止已失效的连接请求报文段出现在新的连接中。客户端在发送完最后一个ACK 报文后,再经过时间2MSL,就可以使由于网络不通畅产生的滞留报文段失效。这样下一个新的连接中就不会出现旧的连接请求报文。清除旧的请求报文。
[
](https://blog.csdn.net/weixin_43901866/article/details/104002207)
