记一记 TCP的三握四挥

文章目录


转自如下两篇文章:

TCP的三次握手与四次挥手理解及面试题(很全面)
面试官,不要再问我三次握手和四次挥手

每次看了TCP的三次握手和四次挥手,总是过一段时间就忘记了,写此文加深理解和记忆。

如下图所示,TCP首部中有很多信息,在这里我们需要关注的是 序号确认号ACK, SYN, FIN标志位
在这里插入图片描述

  • ISN(Initial Sequence Number):初始序列号。
  • ACK(确认字符,Acknowledge Character):占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效。
  • SYN(同步序列编号,Synchronize Sequence Numbers):是TCP/IP建立连接时使用的握手信号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。
  • FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放传输连接。
  • 序号 seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号(ISN)由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号seq就是这个报文段中的第一个字节的数据编号。有了序号才知道传输的数据的顺序,在服务端才能正确组装信息。
  • 确认号 ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。
    PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。

下图表表示了各标志位的含义:
在这里插入图片描述
三次握手:

  • 第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN。此时客户端处于 SYN_SENT 状态。

首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。

  • 第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也指定了自己的初始化序列号 ISN(s)。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_RCVD 的状态。这次握手实际做了两件事,一是告诉客户端收到了其SYN包,二是发送自己的SYN包来请求连接。

在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。

  • 第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED状态,此时,双方已建立起了连接。

确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。

在这里插入图片描述
四次挥手:

  • 第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT_1 状态。
    即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT_1(终止等待1)状态,等待服务端的确认。
  • 第二次挥手:服务端收到FIN之后,会发送 ACK报文,且把客户端的序列号值 +1 作为 ACK报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT_2(终止等待2)状态,等待服务端发出的连接释放报文段。
  • 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。
  • 第四次挥手:客户端收到 FIN 之后,一样发送一个ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
    即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。

在这里插入图片描述

尝试回答下面的问题来确认是否真的理解了。

  1. 为什么需要三次握手,两次不行吗?
  2. 什么是半连接队列?
  3. ISN(Initial Sequence Number)是固定的吗?
  4. 三次握手过程中可以携带数据吗?
  5. SYN攻击是什么?
  6. 为什么连接的时候是三次握手,关闭的时候却是四次握手?
  7. 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
  8. 如果已经建立了连接,但是客户端突然出现故障了怎么办?

这些问题的答案见 :

TCP的三次握手与四次挥手理解及面试题(很全面)
面试官,不要再问我三次握手和四次挥手

猜你喜欢

转载自blog.csdn.net/besmarterbestronger/article/details/107038417
今日推荐