TCP建立连接

  1. 建立连接前,客户端和服务端都处于CLOSED状态。
  2. 先是服务端主动监听某个端口,处于LISTEN状态。
  3. 客户端主动发起第一次握手,之后处于SYN-SENT状态(SYN = 1, seq = x, ACK = 0, ack = 0)。
  4. 服务端收到SYN报文后,返回SYN+ACK报文,之后处于SYN-RCVD状态(SYN = 1, seq = y, ACK = 1, ack = x + 1)。
  5. 客户端收到SYN+ACK之后,返回ACK报文,之后处于ESTABLISHED状态(SYN = 0, seq = x + 1, ACK = 1, ack = y + 1)。
  6. 服务端收到ACK之后,处于ESTABLISHED状态。

TCP断开连接

  1. 断开连接前,客户端和服务端都处于ESTABLISHED状态。
  2. 客户端主动发起FIN报文,并停止再发送数据,之后处于FIN-WAIT-1状态(FIN = 1, seq = u)。
  3. 服务端收到FIN报文后立即发出ACK,然后进入CLOSE-WAIT状态,此时TCP连接处于半关闭状态(seq = v, ACK = 1, ack = u + 1)。
  4. 此时从服务端到客户端这个方向的连接并未关闭,服务端仍可以发送数据到客户端。
  5. 客户端收到ACK报文后,进入FIN-WAIT-2状态,等待服务端发出的FIN报文。
  6. 当服务端发送数据结束后,向客户端发送FIN报文,然后进入LAST-ACK状态(seq = w, ACK = 1, ack = u + 1)。
  7. 客户端收到FIN报文后,向服务端发送ACK报文,然后进入TIME-WAIT状态。此时TCP连接并没有释放,必须经过2MSL后,客户端会CLOSEDseq = u + 1, ACK = 1, ack = w + 1)。
  8. 服务端收到ACK报文后,进入CLOSED状态。

对三次握手的理解

  • 为了实现可靠数据传输,TCP协议的通信双方都必须维护一个序列号,以标识发送出去的数据包中,哪些是已经被对方收到的。
  • 三次握手的过程即是通信双方相互告知序列号起始值,并且要确认对方已经收到了序列号起始值。
  • 确认号的值是告诉发送端自己期待收到的下一个序号,虽然SYN报文不携带数据,但是也要消耗一个序列号,所以ACK报文都要+1。
  • 第一次握手,是客户端告诉服务端的序列号起始值。
  • 第二次握手,是服务端确认收到了客户端的序列号起始值,并且告诉客户端自己的序列号起始值。
  • 第三次握手,是客户端确认收到可服务端的序列号起始值。

对四次挥手的理解

  • FIN报文就是告诉对方,自己没有数据可以发送了。
  • 在建立连接的三次握手中,服务端回复的SYN+ACK是一个合并包,因为它在接收到客户端SYN后,可以立即进行自己的SYN并发送ACK。而在四次挥手中,第二次的ACK和第三次的FIN并不能合并。因为服务端收到客户端的FIN后,它可能还有数据没有发送完毕。它会先回复ACK来确认收到关闭请求,然后继续发送数据。直到数据全部发送完毕后,它才会发出自己的FIN包。
  • 在某些特殊情况下,如果服务端在收到客户端的FIN时,自己的数据也已经发送完毕,那么它可以将ACK和FIN合并在一起发送,这样就会变成三次挥手。但这只是一种特殊优化,标准的关闭流程依然是四次。
  • 第一次挥手,客户端告诉服务端自己已经没有数据可以发送。
  • 第二次挥手,服务端确认了客户端的关闭请求。
  • 第三次挥手,服务端告诉客户端自己已经没有数据可以发送。
  • 第四次挥手,客户端确认了服务端的关闭请求。

2MSL的作用

MSL(Maximum Segment Lifetime)是任何数据包在网络中的最大存活时间。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

  • 保证最后一个ACK的可靠到达

    主动关闭连接的一方发送完最后一个ACK报文后,如果这个ACK报文丢失,接收方(被动关闭方)会超时重发FIN报文。2MSL的时间足够让接收方重发的FIN报文到达发送方,并让发送方能够再次发送ACK报文进行确认,从而保证连接的正常关闭。

  • 避免旧连接的报文段干扰新连接

    在网络中,TCP报文段可能会因为各种原因延迟到达。如果主动关闭方不等待2MSL就立即关闭连接,那么迟到的旧报文段可能会被误认为是新连接的报文段,导致数据错误或连接混乱。2MSL的等待时间确保了这些旧报文段在网络中消失,避免了干扰。

    TIME_WAIT状态正是为了解决这个问题:

    • 在这段时间内,该端口不能被新的连接使用
    • 等待2个MSL,可以确保网络中所有与该旧连接相关的数据包(包括丢失的ACK和重传的FIN)都彻底消失

参考资料