TCP 连接建立过程和连接释放过程

1、客户端A向服务器B发送连接请求报文,此时首部的同步位SYN=1,同时选择一个初始序号seq=x.TCP规定SYN报文(SYN=1)不能携带数据,但是要消耗一个序列号,这时TCP客户进程进入SYN-SENT(同步以发送)状态;

2、服务器B收到连接请求报文后,如果同意建立连接,则向A发送确认,在确认报文中应把SYN和ACK都置为1,确认号是ack=x+1,同时为自己选择一个初始序列号seq=y。同样报文不能携带数据,但是要消耗一个序列号,此时服务器B的进程进入SYN-RCVD(同步收到)状态。

3、客户端A收到服务B的确认后,还要向B给出确认,确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1,TCP的标准规定ACK报文可以携带数据,但是如果不携带数据就不会消耗序号,在这种情况下,下一次数据报文的序号仍为seq=x+1,这时TCP连接已经建立,A进入EXTABLISHED(已建立连接)状态。

连接释放

1、数据传输结束,通信双方都可释放连接,A的进程主动发起连接释放报文。首先将报文首部的终止控制位FIN置1,其序号seq=u(u等于前面已经传输的数据的最后一个字节的序号加1),这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。FIN不携带数据,但是需要消耗一个序号。

2、B收到连接释放报文后随机发出确认,确认号ack=u+1,该报文自己的序号是v,等于前面已发送的数据的最后一个字节的序号加1,B进入CLOSE-WAIT(关闭等待)状态,这时的TCP连接进入半关闭状态。即A已经没有数据要发送了,但是B还有数据要发送,A扔可以接收。A收到了B的确认报文后,进入FIN-WAIT-2(终止等待状态2),等待B发送连接释放报文。

3、若B没有数据向A发送,其应用进程就通知TCP释放连接。这时B发出的连接释放报文必须置FIN=1,假定B的序号是w(半关闭状态下可能又发送了一些数据)B还必须重复上次已发送的确认序号ack=u+1,这时B进入了LAST-ACK状态(最后确认状态),等待A的确认。

4、A收到B的连接释放报文后,必须做出确认,在确认报文中ACK置1,确认号ack=w+1,自己的学号seq=u+1,然后进入TIME-WAIT(时间等待)状态。经过2个MSL后,释放连接。

常见面试题

为什么要三次握手?

  1. 保持信息对等。

  2. 防止请求超时导致脏连接。

两次握手会怎样?

如果两次握手就创建连接,传输完数据并释放连接后,第一个超时的连接请求才到达服务器,服务器会认为是客户端创建新连接的请求,然后创建连接。此时客户端的状态不是SYN_SENT,所以会直接丢弃服务器传来的确认数据,导致最后只是服务器单方面建立了连接。

为什么不直接关闭而是进入TIME_WAIT呢?

  1. 客户端要确认服务器能收到ACK信号。(如果不确认这一点,服务器会认为客户端没有收到自己的FIN+ACK报文,所以会重发)

  2. 防止失效请求。(为了防止已失效的连接的请求数据包和正常的混淆)