前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >令人懵逼的TCP三次握手过程:连接建立,连接管理和连接中断

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

作者头像
望月从良
发布2019-07-10 15:40:11
1.1K0
发布2019-07-10 15:40:11
举报
文章被收录于专栏:Coding迪斯尼Coding迪斯尼

我想任何人只要对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协议为了保证数据传输的稳定性,不得不通过增加协议的复杂性来实现,上面状态描述只是简要描述,很多状态有很多细节依然需要处理,如果你对这些状态及其转换流程依然感觉到糊里糊涂,那不要紧,我们先有一个大概框架,在后面我们代码实现时,很多现在搞不清楚的东西会慢慢变得清晰起来。

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coding迪斯尼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档