建立
要建立TCP连接,需要进行三次握手。
建立连接之前,客户端为CLOSED状态,服务器为LISTENING状态。
建立连接时需要完成:
- 确认双方发送与接收能力正常。
- 同步双方的初始序列号,协商参数(如如最大窗口值、是否使用窗口扩大选项和时间戳选项等)。
第一次握手
客户端→服务器。
客户端向服务器发送一个请求报文段,其中SYN=1,seq=x。
客户端发送报文段后进入SYN_SENT(同步已发送)状态。
第二次握手
服务器→客户端。
客户端收到请求报文段后,向客户端发送确认,其中SYN=1,ACK=1,seq=y,ack=x+1。
服务器收到报文段进入SYN_RCVD(同步已接收)状态。
第三次握手
客户端→服务器。
客户端收到服务器的确认后,向服务器发送确认,其中ACK=1,seq=x+1,ack=y+1。
客户端收到确认后进入ESTABLISHED(连接已建立)状态。
服务器收到对确认的确认后也进入ESTABLISHED状态。
Warning
如果这个确认报文段携带数据,会消耗序列号。
需要三次握手的原因:
- 防止重复建立连接:假如客户端因网络原因超时了,重传了新的报文段(seq不同),如果是两次握手发送确认报文就会建立两次连接,三次握手客户端发现seq不符合就不会建立连接。
释放
要释放已经建立的TCP连接,需要进行四次挥手。
释放连接之前,客户端和服务器都处于ESTABLISHED状态。
第一次挥手
客户端→服务器。
当客户端决定不再发送数据,要关闭TCP连接,就向服务器发送连接释放报文段,其中FIN=1,seq=u(客户端已经发送的数据的最后一个字节的seq+1)。
客户端发送释放报文段后进入FIN_WAIT_1(终止等待1)状态。
第二次挥手
服务器→客户端。
服务器收到释放报文段后,向客户端发送确认,其中ACK=1,seq=v(服务器已经发送的数据的最后一个字节的seq+1),ack=u+1。
此时TCP连接处于半关闭状态,客户端不发送数据,如果服务器发送数据,客户端还要接收。
服务器发送确认后进入CLOSE_WAIT(关闭等待)状态。
客户端接收到确认后进入FIN_WAIT_2(终止等待2)状态。
第三次挥手
服务器→客户端。
当服务器的数据发送完毕了,应用程序通知TCP释放连接,服务器就向客户端发送确认报文段,其中FIN=1,ACK=1,seq=w(半关闭期间可能又发送了数据),ack=u+1。
服务器发送确认后进入LAST_ACK(最后确认)状态。
第四次挥手
客户端→服务器。
当客户端收到服务器的确认后,向服务器发送确认,其中ACK=1,seq=u+1,seq=w+1。
客户端发送确认后,进入TIME_WAIT(时间等待) 状态。
服务器收到确认的确认后,进入CLOSED状态。
客户端进入TIME_WAIT需要再经过2MSL才进入CLOSED状态。
2MSL的作用
- 保证最后第四次挥手到达:假如最后一个确认丢失了,服务器就会超时重传第三次挥手的确认报文段,客户端收到新的确认报文段,就重传确认,并重置超时计时器。
- 防止旧报文段干扰新连接:2MSL的时间,足够本次连接的所有报文段在网络中消失,保证新连接的正常进行。