TCP三次握手和四次挥手,中间失败了会发生什么?
我们都知道TCP建立连接时是三次握手,四次挥手,那么如果中间失败的话会发生什么?
三次握手:
第一次握手丢失了,会发生什么?
当客户端和服务器建立连接的时候,首先会发生一个SYN报文(第一次握手),然后
进入到SYN_SENT状态,假如说SYN丢失的话,即此时客户端一直收不到服务端SYN-ACK
报文(第二次握手),就会触发重传机制,重传SYN报文,而且重传的SYN报文的
序列号都是一样的。
在Linux中,客户端的SYN报文最大重传次数存储在tcp_syn_retries中
通常第一次重传是在1秒后,之后为2秒,等到第6次超时重传后,会等待64秒,如果依然没有收到服务端发送的SYN-ACK,则会断开连接。
第二次握手丢失后,会发生什么?
第二次握手就是服务器给客户端回复的SYN-ACK的过程,此时服务端会进入SYN_RCVD状态。
第二次握手的报文中包含对客户端的第一次ACK的确认报文,如果客户端没有收到服务端发送的SYN-ACK的话,则会以为自己发送的SYN丢失,则会继续重传SYN。
而第二次握手的报文中还包含服务端发送给客户端的SYN,当服务端发送完SYN-ACK后,则会等待接收客户端发送的ACK,因为SYN-ACK丢失了,收不到ACK,所以此时服务端会意识到自己发送的报文丢失了,则会重传SYN-ACK。
SYN-ACK的重传次数存储在tcp_synack_retries中
1. 对于客户端来说: 当客户端重传次数超过tcp_syn_retries时,再等待一段时间,如果还没有收到服务端的第二次握手,则会断开连接。
2.对于服务端来说: 当服务端重传次数超过tcp_synack_retries时,再等待一段时间,如果还没有收到客户端的第三次握手,则会断开连接。
第三次握手丢失了,会发生什么?
客户端收到服务端的SYN-ACK报文后,就会给服务端发送一个ACK报文(第三次握手),此时客户端进入到ESTABLISH状态。
因为第三次握手的ACK是对第二次握手的SYN的确认报文,所以当第三次握手丢失之
后,服务端接收不到客户端发送的ACK,就会以为发送的SYN-ACK丢失了,就会触发
超时重传机制,重传SYN-ACK,之后过程与上面一样。
四次挥手:
可以是服务端方主动发出的,也可以是客户端方主动发出的。
下面是客户端主动关闭连接。
以下都是对于此图(即客户端主动关闭连接)
第一次挥手丢失了,会发送什么?
当客户端调用close()函数后,就会向客户端发送FIN报文,假如当这个FIN报文丢失
了之后,那么客户端将会收不到服务端发送的ACK,则会触发重传机制,重传FIN,
而重传次数存储在tcp_orphan_retries中。
当客户端重发的次数超过tcp_orphan_retries后,就会等待一段时间(此过程与上面将的一样),如果还没有收到ACK,则客户端就会断开连接。
此时我的tcp_orphan_retries的值为0,则它不会重传,则会直接断开连接。
第二次挥手丢失了,会发生什么?
当服务端收到客户端发送的FIN后,就会回复一个ACK(第二次挥手)。此时服务端就会进入到CLOSE_WAIT状态。
假如这个ACK丢失了,客户端就会以为自己发送的FIN报文丢失了,便会触发超时重
传机制,进行重传,此时,重传次数和第一次挥手的重传次数,都是同一个变量,保
存在tcp_orhan_retries中。
假如说超过重传次数后,还没有收到服务端的第二次挥手,那么客户端就会断开连接。
第三次挥手丢失了,会发生什么?
当第二次挥手后,服务端处于CLOSE_WAIT状态,通它此时会等待进程调用close关闭连接,当服务端调用了close之后,内核就会发送FIN报文(第三次挥手),同时进入LAST_ACK状态,等待客户端返回ACK来确认关闭连接。
假如说这个FIN丢失了,那么它此时一直收不到客户端发送的ACK,它此时就会触发
重传机制,重传FIN报文,重传次数依然由tcp_orphan_retries控制。
1.对于服务端来说 : 假如一直丢失FIN,当超过重传次数后,服务端一直接收不到客户端发送的ACK(即第四次挥手),此时服务端就会断开连接。
2.对于客户端来说 : 因为客户端此时处于FIN_WAIT_2状态,这个状态是有时间限制的,为tcp_fin_timeout时间,超过这个时间,还没有收到服务端发送的FIN,而它就会断开连接。
第四次挥手丢失了,会发生什么?
当客户端收到服务端发送的FIN报文后,就会回复ACK报文(即第四次挥手),此时客户端就会进入TIME_WIAT状态。
假如说ACK报文丢失了,服务端一直收不到ACK,则会认为自己发送的FIN丢失了,
则会重新发送FIN,重发次数仍然是tcp_orphan_retries。
在Linux系统中,TIME_WAIT状态会持续2MSL (2倍的MSL ,报文最大生存周期的两倍):网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理之后又会向对方发送响应,所以一来一回最大的时间是2倍的MSL。
根据上面所说,这也是为什么需要TIME_WAIT的原因。
假如说没有TIME_WAIT的话,当第四次挥手丢失之后,服务端重新发送FIN ,而此时发送过来后,已经没有人来处理这个报文了,所以需要TIME_WAIT状态。