Jialong's Blog
沉潜 自由 追寻幸福
TCP三次握手四次挥手详解

三次握手建立连接

  • 第一步:客户机的TCP向服务器的TCP发送连接请求报文段。该报文段的同步位SYN置为1,同时选择一个初始序号seq=x。SYN报文段不能携带数据,但要消耗掉一个序号。这是客户机进入SYN-SENT同步已发送状态。
  • 第二步:服务器的TCP收到连接请求后,如果同意建立连接,则向客户机发回确认,并为该TCP分配缓存和变量。在确认报文段中,SYN和ACK都置为1,确认号是ack=x+1,同时为自己选择一个初始序号seq=y。确认报文不能携带数据,但也要消耗一个序号。此时服务器进入SYN-RCVD同步收到状态。
  • 第三步:客户机收到确认报文后,还要向服务器给出确认,并为该TCP连接分配缓存和变量。确认报文段的ACK置为1,确认号ack=y+1,序号seq=x+1.该报文段可以携带数据,若不携带则不消耗序号。此时TCP客户进程进入ESTABLISH已建立连接状态。

三次握手的原因

第一次客户端发送SYN-SENT后可能在网络中被阻塞,导致超时,客户端重新传输该报文,并与服务器建立连接,之后传输数据然后关闭连接。当被阻塞的连接到达服务器时,服务器认为这个一条新建立的连接,并向客户端发送ACK确认,但客户端将其丢弃,服务器接收不到回复,空等待,造成了资源的浪费。

另一种说法:tcp三次握手只要是为了确认线路的连通,第一次客户端发送到服务端,那么服务端就可以知道客户端的发送没有问题,但客户端不知道服务器的情况,第二次服务器发送ACK给客户端,客户端收到了证明服务端的收发都没有问题的,但服务端不知道客户端的接收情况,所以第三次是客户端再回给服务器一个ACK,服务器收到后就可以确保客户端的收发没有问题。

四次挥手关闭连接

  • 第一步:客户端TCP发送连接释放报文段,并停止发送数据,终止位FIN置为1,序号seq=u,等于之前已经传送的数据的最后一个字节的序号加1,FIN报文段即使不携带数据也要消耗一个序号。此时TCP客户机进入FIN-WAIT-1状态
  • 第二步:服务器收到连接释放报文后即发出确认,确认号ack=u+1,序号seq=v,等于前面已经传输过的数据的最后一个字节的序号加1。然后服务器进入CLOSE-WAIT状态。此时从客户机到服务器的连接就释放了,TCP连接处于半关闭状态。
  • 第三步:若服务器已经没有要向客户机发送的数据,就通知TCP释放连接,此时其发出FIN=1连接释放报文段,该报文段的序号seq=w(在半关闭的时候可能又传输了一些数据),还需重复上次已经发送的确认号ack=u+1.此时服务器进入LAST-ACK状态
  • 第四步:客户机收到连接释放报文段后,要发送确认。把确认报文中的确认位ACK置为1,确认号ack=w+1,序号seq=u+1。此时连接还未释放,要等到计时器的设置时间**2MSL(最长报文寿命)**后客户机才进入CLOSED状态。

粘包

应用层一次recv接收了多个send。原因是TCP协议是面向字节流的,无法区分边界,需要应用层协议去解决。可以通过在应用层为数据流加上特定标志开头。还有就是关闭Nagle协议。


最后修改于 2021-12-09