TCP三次握手及四次挥手学习

TCP是什么?

       TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
       关于TCP具体的知识这儿就不介绍了,下面挑出一些我们需要了解的基本知识进行重温

TCP头部

TCP头部

控制位具体含义

       上面就是TCP协议头部的格式,由于它太重要了,是理解其它内容的基础,下面就将每个字段的信息都详细的说明一下。

  • 源端口号(Source Port)/ 目标端口号(Destination Port)
           表示发送端端口号和接受端端口号,字段长度均为16位(这也解释了为什么端口号的范围是0~65535),源端口号和目标端口号配合上IP首部中的源IP地址和目标IP地址就能唯一地确定一个TCP连接
  • 序列号(Sequence Number)
           字段长度为32位,用来指示发送数据的位置,需要注意的是它不一定从0或1开始,而是在建立连接时由计算机生成的随机数作为初始值;主要用来解决网络报乱序的问题
  • 确认应答号(Acknowlegdement Number)
           字段长度为32位,用来指示下一次应该收到的数据的序列号,实际上它代表了已收到确认应答号减一为止的数据。不过,只有当标志位中的ACK标志为1时该确认序列号的字段才有效。主要用来解决丢包问题
  • 数据偏移(Data Offset)
           给出首部的长度,需要这个值是因为选项字段的长度是可变的。这个字段占4位,每一位表示4个字节(即32位)。因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节
  • 保留(Reserved)
           该字段主要是为了以后扩展时使用
  • 控制位(Control Flag)
    • URG(Urgent Flag)
      该位为1时,表示包中有需要紧急处理的数据,用来保证TCP连接不被中断,对于需要紧急处理的数据,会在后面的紧急指针中再进行解释
    • ACK(Acknowledgment Flag)
      该位为1时,确认应答的字段变为有效。TCP规定除了最初建立连接时的SYN包之外该位必须置为1
    • PSH(Push Flag)
      这个标志位表示Push操作。所谓Push操作就是指在数据包到达接收端以后,立即传送给上层应用协议,而不是在缓冲区中排队
    • RST(Reset Flag)
      该位为1时表示TCP连接中出现异常必须强制断开连接,用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包
    • SYN(Synchronize Flag)
      用于建立连接,置1时表示希望建立连接,并在其序列号的字段进行序列号初始值的设定,通常与ACK搭配使用
    • FIN(Finish Flag)
      表示数据传送完成,没有数据可以传送了,当通信结束希望断开连接时,通信双方的主机之间就可以交换FIN位置为1的TCP段
  • 窗口大小(Window Size)
           该字段长为16位,用于通知从相同TCP首部的确认应答号所指位置开始能够接收的数据大小(8位字节)。TCP不允许发送超过此处所示大小的数据。另外,窗口为0时可用于发送窗口探测,以了解最新的窗口大小,但这个数据必须是1字节

三次握手及四次挥手

TCP三次握手及四次挥手

接下来就是今天的重头戏,首先是借由上图对两个“手”的过程的流程解读

三次握手

       当我们需要通过TCP来传输数据时,就必须让客户端和服务端建立连接,这就是所谓的“三次握手”

1.第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Seq为x;接着客户端进入SYN_SEND状态,等待服务端的确认

2.第二次握手:服务端收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Ack为x+1(即Seq+1);同时,自己还要发送SYN请求信息,将SYN位置为1,Seq为y;服务端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态

3.第三次握手:客户端收到服务器的SYN+ACK报文段后将Ack设为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手

完成了三次握手,客户端和服务器端就可以开始愉快地传送数据啦~

四次挥手

       那么当数据传输完毕后,我们必然会面临断开连接的问题,这个时候就需要“四次挥手”出场了~

1.第一次挥手:主机1(客户端或服务器端均可),设置Seq和Ack,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了

2.第二次挥手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求,但我可能还有数据需要传输,所以不要立即关闭

3.第三次挥手:主机2向主机1发送FIN报文段,表示我这已经准备好了,随时可以关闭连接了,同时主机2进入LAST_ACK状态

4.第四次挥手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明服务端已正常关闭,那么主机1也可以关闭连接了

       到这里,一个完整的TCP建立连接 => 传送数据 => 断开连接的流程就结束了,然后就是处理一些常见的疑问(别称:面试题)

疑问1:为什么必须是四次挥手呢?把第二次挥手和第三次挥手合为一次不行吗?
答:关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET(因为此时数据很可能未传输完毕),暂且只能先回复一个ACK报文,告诉客户端,"你发的FIN报文我收到了"。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。

疑问2:三次握手中最后一次握手不能直接去掉吗?
答:在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。什么意思呢?假设我们将其改为两次握手,那么如果A发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求,而后收到确认后建立好了连接,接着该干嘛该干嘛,最后把连接断开就完事儿了。但是,这时候上一个丢失的报文突然又冒出来传到服务端去了,服务端接收后返回确认报文,按照我们假设的情况,这时候本不该建立的连接便建立起来了,可客户端本就无意建立连接,也就不会发送数据给服务端,服务端就一直干等着,浪费资源。

疑问3:为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSED状态?
答:TIME_WAIT状态其实是用来重发可能丢失的ACK报文,为啥呢?你想啊,要是最后一次挥手发出去的ACK报文不见了咋办,这时候服务端就不断地抛FIN给客户端,问“我可以结束了呀,你咋不理我了呢”,但客户端早早地就进入CLOSED态,谁还理你呀~因此需要客户端设置一个定时器来防止这种窘境的出现,在这段时间里如果你没重复发送FIN给我,那我就默认你收到我的报文了,于是断开连接

参考资料(感谢各位前辈大佬)

  • 通俗大白话来理解TCP协议的三次握手和四次分手
  • TCP的三次握手与四次挥手过程的每一步的具体状态变换
  • TCP三次握手详解及释放连接过程
  • TCP四次挥手简介
  • 《图解TCP/IP》

你可能感兴趣的:(TCP三次握手及四次挥手学习)