TCP连接3次握手与4次挥手理解

(1)seq: ***,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;***seq就是这个报文段中的第一个字节的数据编号。
(2)ack: 确认号,占32位,只有ACK标志位为1时确认序号字段才有效,ack=seq+1。
占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;***表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。
确认方ack=发起方seq+1

(3)大写的单词表示标志位,其值要么是1,要么是0。标志位共6个,即ACK、SYN、FIN、PSH、RST、URG等,具体含义如下:

  • ACK:验证字段,占1位,TCP规定仅当ACK=1时确认号字段ack才有效,ACK=0时确认号无效,也规定连接建立后所有发送的报文的ACK必须为1。
  • SYN:在连接建立时用于同步序号。当SYN=1而ACK=0时,表明这个是一个连接请求报文。对*同意建立连接,则响应报文中SYN=1,ACK=1。因此,SYN置1表示这是一个连接请求或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。
  • FIN(finish):用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已经发送完毕,并请求释放断开TCP连接。
  • URG:紧急指针(urgent pointer)有效。
  • PSH:接收方应该尽快将这个报文交给应用层。
  • RST:重置连接。

3(ThreewayHandshake)\color{#FF3030}{3次握手(Three-way Handshake)}:是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
TCP连接3次握手与4次挥手理解
  握手之前主动打开连接的客户端结束CLOSED阶段,被动打开的服务器端也结束CLOSED阶段,并进入LISTEN阶段。随后开始“三次握手”:
  \color{orange}{第一次握手:}客户端向服务器发送连接请求报文,其中:

  • 标志位SYN=1,表示请求建立连接。
  • ***seq=x,x是任意正整数的值。
  • 随后客户端进程进入SYN-SENT(同步已发送)状态。
    此时发送过去的数据包即报文段被称为SYN报文段,它是不可以携带数据的。但是会消耗掉一个序号,这便是第一次握手。

  \color{orange}{第二次握手:}当服务器接收到请求报文后,会结束LISTEN状态并返回一段确认报文,其中:

  • 两个标志位SYN=1,ACK=1,表示客户端的报文seq***有效,服务器能正常接收客户端发送的数据,并同意创建新连接(即告诉客户端,服务器收到了你的数据);
  • 序号为Seq=y;
  • 确认号为ack=x+1。由于客户端发送的SYN报文中***seq=x,服务器端为了回应客户端,要回应和x相关的信息,ack=x+1表示服务器收到客户端的***并将其值加1作为自己确认号ack的值;随后服务器端进入SYN-RCVD(同步已收到)状态。该报文也是不可以携带数据的,并且同样需要消耗一个序号,这便是第二次握手。

  \color{orange}{第三次握手:}客户端接收到来自服务器端的确认报文之后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段。并向服务器发送最后一段确认报文。其中:

  • 标志位为ACK=1,表示“确认收到服务器端同意连接的信号”(即告诉服务器,我知道你收到我发的数据了);
  • ***为seq=x+1,表示收到服务器端的确认号ack,并将其值作为自己的***值;
  • 确认号为ack=y+1,因为服务器发送的报文里面seq=y,而客户端为了回应服务器端,要回应和y相关的信息,ack=y+1表示收到服务器端序号seq,并将其值加1作为自己的确认号ack的值;
  • 随后客户端进入ESTABLISHED(连接已建立)阶段。

  服务器收到来自客户端的“确认收到服务器数据”的TCP报文之后,明确了从服务器到客户端的数据传输是正常的。结束SYN-SENT阶段,进入ESTABLISHED阶段。此为第3次握手。
  此后客户端和服务器端进行正常的数据传输。
  在客户端与服务器端传输的TCP报文中,双方的确认号ack和序号seq的值,都是在彼此ack和seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续"握手",以此确保了"三次握手"的顺利完成。
  握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP连接都将被一直保持下去。若在握手过程中某个阶段莫名中断,TCP协议会再次以相同的顺序发送相同的数据包。

4\color{#FF3030}{4次挥手}:由于TCP连接是全双工的,当数据传输完毕之后,每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。客户端和服务器端都可以主动断开连接,最开始的时候,客户端和服务器端都处于ESTAB-LISHED状态即连接已建立。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。以下是当客户端主动关闭服务器端被动关闭时的挥手流程。
TCP连接3次握手与4次挥手理解
挥手之前主动释放连接的客户端结束ESTABLISHED阶段。随后开始“四次挥手”:

\color{orange}{第一次挥手:}首先客户端想要释放连接,向服务器端发送一段TCP报文,其中:

  • 标记位为FIN=1(请求断开连接),表示自己已经没有数据要发送了。
  • ***为seq=u;u等于前面ESTAB-LISHED状态下数据最后一次发送已经传送过来的数据最后一个字节的序号加一。
  • 随后客户端进入FIN-WAIT-1(终止等待1)阶段。并且\color{orange}{停止从客户端向服务器端发送数据},但是客户端仍然能接收从服务器端传输过来的数据。\color{#FF3030}{注意:}这里停止发送的是正常连接时传输的数据,确认报文依然可以发送。TCP规定,即使FIN报文段不携带任何数据,也要消耗一个***。即服务器端回值的时候ack=u+1。这就是第一次挥手。

  当然,在FIN包之前发送出去的数据,如果没有收到对应的ACK确认报文,主动关闭方依然会重发这些数据,但是,此时主动关闭方还可以接受数据。

\color{orange}{第二次挥手:}服务器端接收到从客户端发出的TCP报文之后,确认了客户端想要断开连接并向客户端发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。随后服务器端结束ESTABLISHED阶段,进入CLOSE-WAIT阶段(关闭等待)。确认包中:

  • 标记位为ACK=1,表示“接收到客户端发送的断开连接的请求”;
  • ***为seq=v;
  • 确认号为ack=u+1,表示是在收到客户端报文的基础上,将其序号seq值加1作为本段报文确认号ack的值;
  • 随后服务器端开始准备释放服务器端到客户端方向上的连接。
  • 客户端收到从服务器端发出的TCP报文之后,确认了服务器收到了客户端发出的释放连接请求,随后客户端结束FIN-WAIT-1阶段,进入FIN-WAIT-2阶段。这就是第二次挥手。

  前"两次挥手"既让服务器端知道了客户端想要释放连接,也让客户端知道了服务器端了解了自己想要释放连接的请求。于是,可以确认关闭客户端到服务器端方向上的连接了。

\color{orange}{第三次挥手:}服务器端自从发出ACK确认报文之后,经过CLOSED-WAIT阶段,发送完数据后,再次向客户端发出一段TCP报文,其中:

  • 标记位为FIN=1,ACK=1,表示“已经准备好释放连接了”。注意:这里的ACK并不是确认收到服务器端报文的确认报文。
  • ***为seq=w;
  • 确认号为ack=u+1;表示是在收到客户端报文的基础上,将其序号Seq值加1作为本段报文确认号Ack的值。
  • 随后服务器端结束CLOSE-WAIT阶段,进入LAST-ACK阶段。并且停止在服务器端到客户端的方向上发送数据,但是服务器端仍然能够接收从客户端传输过来的数据(这里的数据仅仅是确认报文)。

\color{orange}{第四次挥手:}客户端接收到来自服务器端的关闭请求,发送一个确认包,并结束FIN-WAIT-2阶段,进入TIME-WAIT阶段,等待可能出现的要求重传的 ACK 包。同时向服务器端发送一段确认报文,其中:

  • 标记位为ACK=1,表示“接收到服务器准备好断开连接的信号”。
  • 序号为seq=u+1;表示是在收到了服务器端报文的基础上,将其确认号ack值作为本段报文序号的值。
  • 确认号为ack=w+1;表示是在收到了服务器端报文的基础上,将其序号seq值作为本段报文确认号的值。
  • 随后客户端开始在TIME-WAIT阶段等待2MSL(2乘以MSL时间,MSL是最长报文段寿命)。

  服务器端接收到这个确认包之后,立即关闭连接进入 CLOSED 状态。客户端等待2MSL之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态(服务器端结束TCP连接时间比客户端结束TCP连接的时间稍早一些)。这就是第四次挥手。
  即主动断开连接方发送断开连接请求,被动方返回收到消息报文,被动方处理完数据后发送确认断开连接报文,主动方返回收到确认并断开。

第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接受数据。
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1。
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

3次握手4次挥手期间连接双方状态声明:

  • CLOSED: 这个表示初始状态(这是为方便描述假想的状态,实际不存在)。
  • LISTEN(服务器): 表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
  • SYN_RCVD(服务器): 这个状态表示接受到了请求连接报文,很短暂。
  • SYN_SENT: 这个状态与SYN_RCVD呼应,当客户端发送SYN请求连接报文后等待对方回应时处于此状态。
  • ESTABLISHED:表示连接已经成功建立。
  • FIN_WAIT_1: 当主动断开连接方发送断开请求并等待对方第一次回应(第二次挥手)时处于此状态。
  • FIN_WAIT_2:当主动断开连接方收到对方第一次回应(第二次挥手)并等待第二次回应(第三次挥手)期间处于此状态。
  • -CLOSE_WAIT: 被动关闭方在发送第二次挥手和第三次挥手期间处于该状态。
  • TIME_WAIT: 当主动断开连接方收到对方第二次回应(第三次挥手),发送确认报文(第四次挥手)并等待2MSL回到CLOSED可用状态期间处于此状态。TIME_WAIT 两个存在的理由:
    1.尽最大努力保证四次握手正常关闭,可靠的实现tcp全双工连接的终止;
    2.确保老的报文段在网络中消失,不会影响新建立的连接.。
  • LAST_ACK: 被动关闭方在进行完第三次挥手等待主动方的确认报文期间处于此状态。

参考于:
https://baijiahao.baidu.com/s?id=1654225744653405133&wfr=spider&for=pc
https://www.cnblogs.com/biehongli/p/11964057.html
https://www.cnblogs.com/ranyonsue/p/5984001.html