专栏首页Coding迪斯尼令人懵逼的TCP三次握手过程:连接建立,连接管理和连接中断

令人懵逼的TCP三次握手过程:连接建立,连接管理和连接中断

我想任何人只要对TCP协议有一丁点了解,都会知道它有一个三次握手过程。然而你未必知道这三次握手过程其实非常复杂,而且成本很高,很多上层协议就是为了避免三次握手带来的通讯延迟而放弃TCP协议的稳定性,转而依赖UDP,后者虽然数据传输没有保障,但是速度快,QQ通讯最早使用的就是UDP。

TCP是一个比较”沉重“的协议,也就是为了保证数据传输万无一失,它必须要采取很多烦琐的保障措施。它在连接建立时会启动一个复杂的状态机来管理连接状态,协议会根据不同的情况,从当前所属状态进入另一个状态并采取相应的措施。

TCP在连接,数据发送,断开连接的整个过程中可以简单的用三个状态来表示。第一个状态叫SYN,处于该状态时,通讯双方开始建立连接,同时双方协商好数据包的序列号。第二个状态叫FIN,此时所有数据发送完毕,其中一方像另一方发送断开连接的消息,然后自己进入连接断开状态。第三个状态叫ACK,它用来回复自己受到了对方发送过来的数据包。

如果我们把上面简化的三种状态再度细化,那么整个通讯过程其实分为11种状态,我们分别看每种状态的描述: 1, Closed。当双方处于没有联系的状况时,他们就处于关闭状态。根据通讯双方的角色,他们会通过不同的方式进入下一个状态。如果是服务器,它在开始通讯前会经过所谓的消极启动方式,也就是他会选择一个端口号,初始化一个socket结构,然然进入监听状态,此时它准备随时迎接客户端连接请求。如果是客户端,那么它会经过积极启动步骤,也就是主动向服务器发送一个SYN,也就是请求建立连接的消息。 2,Listen。这个状态属于服务器才有,它时刻准备处理来自客户端的连接和数据发送请求,如果它收到客户端发来的SYN数据包,它会回复SYN+ACK数据包,然后进入SYN-RECEIVED状态,此时它准备与客户端发送或接受数据。

这里需要提及什么叫SYN,或SYN+ACK数据包。在上一节我们曾用wireshark抓去过TCP数据包:

所谓SYN,ACK其实就是在Flag字段将某个比特位开启,这些比特位的作用我们在协议实现时会详细讲解。

3,SYN-SEND。这个状态一般是客户端才有,它向服务器发送SYN数据包请求建立连接后就会进入该状态,它等待对方发送一个SYN数据包回来。如果服务器发回数据包中只有SYN状态没有ACK状态,那么它就会回发一个ACK数据包,然后进入SYN-RECEICED状态,然后等待对方也回发一个ACK数据包。如果服务器发来的包包含SYN和ACK状态,那么它直接进入ESTABLISHED状态,也就是说它进入连接建立完成的状态。

4,SYN-RECEIVED,这个状态客户端才有,这种状况的出现是因为客户端发送SYN数据包请求建立连接,但是服务器端只回发一个SYN数据包,其中没有启动ACK比特位,这表示服务器知道客户端想建立连接,但服务器还没准备好,此时它只能等待,知道对方发送一个ACK包过来,然后进入ESTABLISHED状态。

5,ESTABLISHED。进入这个状态表示三次握手已经完成,双方可以开始进行数据交换,这个状态知道数据发送完毕才或通讯出现异常后转让连接断开阶段。一种情况是本方想断开连接,于是本方向对方发送的FIN数据包,然后进入FIN-WAIT-1状态。一种情况是对方想断开连接,于是对方发来了FIN数据包,然后本方发送一个ACK数据包,接着进入CLOSE-WAIT状态。

6,CLOSED_WAIT。通讯的一方接收到另一方关闭连接的通知数据包FIN,此时客户端的TCP协议层将对方要关闭连接的消息发送给当前进程,等待上层应用处理连接关闭事件,然后它向对方发送一个FIN数据包,并等待对方回发一个ACK数据包,同时进入到LAST-ACK状态。

7,LAST-ACK。当前设备收到了对方发来的关闭连接通知包FIN,同时也回发了ACK,以及自己向对方也发送了FIN数据包,此时等待对方发过来ACK数据包以便确认对方收到了本方发出的FIN数据包。当收到对方发来的ACK包后,本方进入CLOSED状态,双方的连接成功断开。

8,FIN-WAIT-1。当前设备发送给对方FIN包要求断开连接后,等待对方发回ACK数据包,或者是等待对方发出FIN数据包。如果本方发送FIN包,然后收到对方发来的ACK包,那么就进入FIN-WAIT-2状态,如果等到的不是ACK包而是对方发来的FIN包,那么就进入CLOSING状态。

9, FIN-WAIT-2。本方发送FIN要求断开连接,然后收到了对方回发的ACK包后进进入该状态,此时它等待对方发送FIN包过来,当成功等到对方发来的FIN包后,它立马回发ACK包然后进入到TIME-WAIT状态。

10,CLOSING。当前设备收到对方发来中断连接的FIN数据包后也回发了ACK确认数据包,然后自己也发送了FIN数据包,当还没等到对方发来的ACK确认数据包。如果成功等到了对方发来的ACK数据包后,它会进入到TIME-WAIT状态。

11,TIME-WAIT。当前设备收到对方发来的FIN中断连接数据包,然后也回发了ACK数据包。接着它自己又向对方发送了FIN数据包,然后也收到了对方发来的ACK确认数据包。此时理论上连接已经成功断开,当设备需要等待一会,以便确定对方接收到自己发出的ACK包,等待一段时间后自动进入CLOSED状态。

上面的状态转换过程请看下图:

不知道你看到上面的状态转换图时,有没有被转来绕去的路径给搞懵逼,反正我是懵了,TCP协议为了保证数据传输的稳定性,不得不通过增加协议的复杂性来实现,上面状态描述只是简要描述,很多状态有很多细节依然需要处理,如果你对这些状态及其转换流程依然感觉到糊里糊涂,那不要紧,我们先有一个大概框架,在后面我们代码实现时,很多现在搞不清楚的东西会慢慢变得清晰起来。

新书上架,请诸位朋友多多支持:

本文分享自微信公众号 - Coding迪斯尼(gh_c9f933e7765d),作者:陈屹

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • TCP三次握手详解:传输控制块TCB以及积极和消极的连接建立方式

    TCP协议目的是为了保证数据能在两端准确连续的流动,可以想象两个建立起TCP通道的设备就如同接起了一根水管,数据就是水管中的水由一头流向另一头。然而TCP为了能...

    望月从良
  • java实现FTP协议:wireshark抓包解析

    本节我们看看ftp协议的数据包格式,同时使用代码加以实现。首先我们现在机器上安装ftp服务器,我在自己的机器上安装了QuickFTP Server,它是我随便找...

    望月从良
  • 使用java自造TCP/IP协议栈:使用JPCAP实现数据发包

    从本节开始,我们打算使用java把tcp/ip网络协议栈重新实现一遍。这是一个不小的野心,自然也是一个不小的工程,好在前面顺利完成了操作系统,编译器两门课程的实...

    望月从良
  • DDoS攻击:无限战争

    经过黑衣人和老周的合作,终于清除了入侵Linux帝国的网页病毒,并修复了漏洞。不曾想激怒了幕后的黑手,一场新的风雨即将来临。

    轩辕之风
  • FunTester测试框架视频讲解(序)

    本人使用Java语言基于httpclient做了一个测试框架,包括功能、自动化和性能测试的能力,之前都是写一些文章分享一些案例,打算做一些新的尝试,希望效果能比...

    八音弦
  • 云主机的指令集配置

    一些高性能计算应用需要CPU支持某些特性,如SSE4.2、 AVX、 AVX2、LZCNT、 FMA、 BMI等。OpenStack 默认的配置项为了保持虚拟机...

    后端云
  • Qt编写安防视频监控系统8-双击节点

    在所有的视频监控系统中,双击摄像机的节点,对应摄像机加载到当前焦点通道显示,这个都是必须具备的功能,还有一些厂家会做双击NVR节点,自动加载该NVR下的所有摄像...

    feiyangqingyun
  • java设计模式之代理模式【设计模式】

    张三想要去日本某公司买xxx,但是对于经费等等一系列的原因然后就放弃了这个念头,我刚好要去日本玩的,张三得知我要去日本,他就偷偷给我说,他想要一个size为D的...

    奕仁
  • 学linux,全靠这些了

    使用 date 修改 Linux 上的系统时间 date 命令不光能显示时间,还能修改系统上的时间。

    DataScience
  • python 发送邮件 附件名为中文

    用户5760343

扫码关注云+社区

领取腾讯云代金券