|
|
51CTO旗下网站
|
|
移步端
  • TCP三次握手、四次挥手出现意外情况时,如何保证稳定可靠?

    咱们在读书 TCP 建连和断连时,大多数都在说一个标准的流程,但是网络环境是形成的,有的是时候并不像教科书那样标准,这就是说今天就来聊聊,TCP 三次握手和四次挥手时,如果出现异常状态,是如何处理的?又是由谁来处理?

    笔者:承香墨电影 来源:承香墨电影| 2020-02-13 21:30

    本文是先前分多篇发布之篇章,如今整理成一篇发布,调整了部分小细节。

    一、先后

    顶我们聊到TCP 协和的时节,聊的最多的就是三次握手与四次挥手。但是大部分资料和文章,写的都是健康的情况下的流程。但是你有没有想过,三次握手或者四次挥手时,如果发生异常了,是如何处理的?又是由谁来处理?

    TCP 表现一个靠谱的商谈,在传输数据的左右,要求在双端之间确立连接,并在双端各自维护连接的状态。TCP 并没有什么特别的处,在面对多变的网络情况,也只能通过不断的份额传和各族算法来保证可靠性。

    确立连接前,TCP 会通过三次握手来保证双端状态不错,下一场就足以正常传输数据了。顶数据传输完成,要求断开连接的时节,TCP 会通过四次握手来形成双端的断连,并回收各自的风源。

    咱们在读书 TCP 建连和断连时,大多数都在说一个标准的流程,但是网络环境是形成的,有的是时候并不像教科书那样标准,这就是说今天就来聊聊,TCP 三次握手和四次挥手时,如果出现异常状态,是如何处理的?又是由谁来处理?

    二、TCP 三次握手

    1. 大概理解三次握手

    虽然是说三次握手的突出状态,咱们还是先来了解一下三次握手。

    在通过 TCP 传输数据时,着重步就是中心先建立一个连接。TCP 确立连接的经过,就是我们常说之三次握手。

    咱们经常将三次握手,叙述成「呼吁 → 应答 → 应答之应答」。

    至于 TCP 拉手为什么是三次?其实就是中心让双端都经历一次「呼吁 → 应答」的经过,来确认对方还在。网络情况是形成的,双端都要求一次自己主动发起的呼吁和美方回答的回复过程,来确保对方和网络是健康的。

    下这张图,是比较经典的 TCP 三次握手的信息和双端状态的转移。

    咱们先来诠释一下这张图:

  • 在始发时,双端处于 CLOSE 状态,劳务端为了提供服务,会积极监听某个端口,进去 LISTEN 状态。
  • 客户端主动发送连接的「SYN」包,后进入 SYN-SENT 状态,劳务端在接受客户端发来之「SYN」包后,回复「SYN,ACK」包,后进入 SYN-RCVD 状态。
  • 客户端收到服务端发来之「SYN,ACK」包后,可以肯定对方存在,此刻回复「ACK」包,并进入 ESTABLISHED 状态。
  • 劳务端收到最后一个「ACK」包后,也进入 ESTABLISHED 状态。
  • 这是健康的 TCP 三次握手,拉手完成后双端都进入 ESTABLISHED 状态,在此之后,就是健康的数据传输过程。

    2. TCP 握手的突出状态

    三次握手的健康发包和回答,以及双端的状态扭转我们已经讲了,然后就来看望在这三次握手的经过中,出现的突出状态。

    (1) 客户端第一个「SYN」包丢了。

    如果客户端第一个「SYN」包丢了,也就是劳动端根本就不知晓客户端曾经发过包,这就是说处理流程主要在客户端。

    而在 TCP 协和中,某端的一组「呼吁-应答」官方,在固定时间范围内,只要没有接受应答的「ACK」包,不论请求包对方没有接受,还是对方的回答包自己没有接受,平均认为是丢包了,都市触发超时重传机制。

    故此此时会进入重传「SYN」包。根据《TCP/IP详解卷Ⅰ:协和》中的描述,此刻会尝试三次,间隔时间分别是 5.8s、24s、48s,三次时间大约是 76s 控制,而大多数伯克利系统将成立一个新连接的最长时间,限制为 75s。

    具体地说三次握手第一个「SYN」包丢了,会重传,总的尝试时间是 75s。

    (2) 劳务端收到「SYN」并回复的「SYN,ACK」包丢了。

    此刻服务端已经收到了数据包并回复,如果这个回复的「SYN,ACK」包丢了,站在客户端的力度,会以为是最开始的那个「SYN」丢掉了,这就是说就继续重传,就是我们面前说的「错误 1」 的流程。

    而对劳动端而言,如果发送的「SYN,ACK」包丢了,在超时时间内没有收到客户端发来之「ACK」包,也会触发重传,此刻服务端处于 SYN_RCVD 状态,会依次等待 3s、6s、12s 此后,重新发送「SYN,ACK」包。

    而这个「SYN,ACK」包的份额传次数,不同之操作系统下有不同之安排,例如在 Linux 从可以通过 tcp_synack_retries 拓展布局,默认值为 5。如果这个重试次数内,仍未接到「ACK」应答包,这就是说服务端会自动关闭这个连接。

    同时由于客户端在没有接受「SYN,ACK」时,也会进展重传,顶客户端重传之「SYN」把接受后,劳务端会立即重新发送「SYN,ACK」包。

    (3) 客户端最后一次回复「SYN,ACK」的「ACK」包丢了。

    如果最终一个「ACK」包丢了,劳务端因为收不到「ACK」会走重传机制,而客户端此时进入 ESTABLISHED 状态。

    大多数情况下,客户端进入 ESTABLISHED 状态下,则认为连接已成立,会立即发送数据。但是服务端因为没有接受最后一个「ACK」包,依然处于 SYN-RCVD 状态。

    这就是说这里的严重性,就在于服务端在处于 SYN-RCVD 状态下,接受客户端的数据包后如何处理?

    这也是比较有争议之中央,局部资料里会写到当服务端处于 SYN-RCVD 状态下,接受客户端的数据包后,会直接回答 RTS 包响应,表示服务端错误,并进入 CLOSE 状态。

    但是这样的设定有些过于严格,预计一下,劳务端还在通过三次握手阶段确定对方是否真正生活,此刻对方的多寡已经发来了,那肯定是生活的。

    故此当服务端处于 SYN-RCVD 状态下时,接受到客户端真实发送来的数据包时,会以为连接已成立,并进入 ESTABLISHED 状态。

    这就是说实际状况,为什么会这样呢?

    顶客户端在 ESTABLISHED 状态下,起来发送数据包时,会携带上一度「ACK」的承认序号,故此哪怕客户端响应的「ACK」包丢了,劳务端在接受这个数据包时,能够通过包内 ACK 的承认序号,正常进入 ESTABLISHED 状态。

    (4) 客户端故意不发最后一次「SYN」包。

    眼前一直在说正常的突出逻辑,两岸都还算友善,按规矩办事,出现异常主要也是因为网络等客观问题,然后说一个恶意的状况。

    如果客户端是恶意的,在殡葬「SYN」包后,并接受「SYN,ACK」此后就不回答了,这就是说服务端此时处于一种半连接的状态,虽然服务端会通过 tcp_synack_retries 安排重试的用户数,不会无限等待下去,但是这也是有一度时间周期的。

    如果短时间内存在大量之这种恶意连接,对劳动端来说压力就会很大,这就是所谓的 SYN FLOOD 攻击。

    这就属于安全攻防的框框了,当日就不讨论了,有兴趣可以自动了解。

    三、TCP 四次挥手

    1. 大概理解四次挥手

    说完 TCP 三次握手,继承来分析 TCP 四次挥手的突出状态。

    保持行文风格,在此之前,咱们还是先来概括了解一下 TCP 的四次挥手。

    顶数据传输完成,要求断开连接的时节,TCP 会利用四次挥手的措施,来安全的断开连接。

    为什么握手需要三次,而挥手需要四次呢?

    实质上来说,双端都要求经过一次「离别」的经过,来保证自己和对头的状态不错。本着友好协商的态势,你先提出的分别,也要把最大的好心�o美方,决不能打了我党一个措手不及。你说不玩了就不玩了,那以后谁还敢和你玩。

    下这张图,是比较经典的 TCP 四次挥手的信息和双端状态的转移。

    咱们解释一下这张图:

  • 初步时双端还都处于 ESTABLISHED 状态并传输数据,某端可以主动发起「FIN」包准备断开连接,在此间的面貌下,是客户端发起「FIN」呼吁。在发射「FIN」此后,客户端进入 FIN-WAIT-1 状态。
  • 劳务端收到「FIN」信息后,回复「ACK」表示理解了,并从 ESTABLISHED 状态进入 CLOSED-WAIT 状态,起来做一些断开连接前的准备工作。
  • 客户端收到之前「FIN」的回答「ACK」信息后,进去 FIN-WAIT-2 状态。而当服务端做好断开前的准备工作以后,也会发送一个「FIN,ACK」的信息�o客户端,表示我也好了,呼吁断开连接,并在殡葬消息后,劳务端进入 LAST-ACK 状态。
  • 客户端在接受「FIN,ACK」信息后,会立即回复「ACK」,表示理解了,并进入 TIME_WAIT 状态,为了稳定和安全考虑,客户端会在 TIME-WAIT 状态等待 2MSL 的时长,末了进入 CLOSED 状态。
  • 劳务端收到客户端回复的「ACK」信息后,直接从 LAST-ACK 状态进入 CLOSED 状态。
  • 正常的经过四次挥手之后,双端都进入 CLOSED 状态,在此之后,双端正式断开了交接。

    2. TCP 挥手的突出状态

    四次挥手的健康发包和回答过程,咱们已经简单了解了,然后就继续看看,四次挥手过程中,出现的突出状态。

    (1) 断开连接的 FIN 包丢了。

    咱们面前一直强调过,如果一个包发出去,在固定时间内,只要没有接受对头的「ACK」回复,平均认为这个包丢了,会触发超时重传机制。而不会关切到底是团结发的包丢了,还是对方的「ACK」丢掉了。

    故此在此间,如果客户端率先发的「FIN」包丢了,或者没有接受对头的「ACK」回复,则会触发超时重传,直到触发重传之用户数,直接关闭连接。

    对于服务端而言,如果客户端发来之「FIN」没有接受,就没有其他感知。会在一段日子后,也关闭连接。

    (2) 劳务端第一次回复的 ACK 丢掉了。

    此刻因为客户端没有接受「ACK」应答,会尝试重传之前的「FIN」呼吁,劳务端收到后,又会立即再重传「ACK」。

    而此时服务端已经进入 CLOSED-WAIT 状态,起来做断开连接前的准备工作。顶准备好之后,会回复「FIN,ACK」,瞩目这个消息是携带了之前「ACK」的呼唤序号的。

    只要这个消息没少,客户端可以凭借「FIN,ACK」包中的响应序号,直接从 FIN-WAIT-1 状态,进去 TIME-WAIT 状态,起来长达 2MSL 的等待。

    (3) 劳务端发送的 FIN,ACK 丢掉了。

    劳务端在超时后会重传,此刻客户端有两种情景,要么处于 FIN-WAIT-2 状态(先前的 ACK 也丢了),会一直等待;要么处于 TIME-WAIT 状态,会等待 2MSL 时光。

    具体地说,在一小段日子内客户端还在,客户端在接受服务端发来之「FIN,ACK」包后,也会回复一个「ACK」应答,并搞好协调之状态切换。

    (4) 客户端最后回复的 ACK 丢掉了。

    客户端在回答「ACK」此后,会进入 TIME-WAIT 状态,起来长达 2MSL 的等待,劳务端因为没有接受「ACK」的回答,会重试一段日子,直到劳动端重试超时后主动断开。

    或者等待新的客户端接入后,接受服务端重试的「FIN」信息后,回复「RST」信息,在接受「RST」信息后,复位服务端的状态。

    (5) 客户端收到 ACK 此后,劳务端跑路了。

    客户端在接受「ACK」此后,进去了 FIN-WAIT-2 状态,等待服务端发来之「FIN」包,而如果服务端跑路了,其一包永远都等不到。

    在 TCP 协和中,是没有对这个状态的拍卖体制的。但是协议不管,系统来凑,操作系统会接管这个状态,例如在 Linux 从,就足以通过 tcp_fin_timeout 数,来对这个状态设定一个超时时间。

    要求注意的是,顶超过 tcp_fin_timeout 的限制后,状态并不是改制到 TIME_WAIT,而是直接进入 CLOSED 状态。

    (6) 客户端收到 ACK 此后,客户端自己跑路了。

    客户端收到「ACK」此后直接跑路,劳务端后续在殡葬的「FIN,ACK」就没有接到端,也就不会得到答复,会不断的往来 TCP 的逾期重试的公有制,此刻服务端处于 LAST-ACK 状态。

    那就要分 2 种情景分析:

  • 在超过一定时间后,劳务端主动断开。
  • 接受「RST」此后,再接再厉断开连接。
  • 「RST」信息是一种重置消息,表示当前错误了,有道是回到初始的状态。如果客户端跑路后有新的客户端接入,会在此发送「SYN」以期望建立连接,此刻这个「SYN」名将把忽视,并直接回答「FIN,ACK」信息,新客户端在接受「FIN」信息后是不会认的,并且会回复一个「RST」信息。

    四、总结时刻

    本文聊了 TCP 在三次握手和四次挥手的时节,出现异常的拍卖逻辑。

    绝大多数情况下,都是依托超时重传来保证 TCP 的可靠性,但是重传之用户数,状态的更换,以及有哪些状态是把系统接管,该署细节,就是本文的主题。

    【编纂推荐】

    1. TCP 三次握手背的滚瓜乱熟,那意外情况呢?丢包了呢?故意不回答 ACK 呢?
    2. 三次握手+四次挥手,一文搞定所有!
    3. TCP 四次挥手,你熟了!那意外情况呢?恶意攻击呢?单端跑路呢?
    4. 为什么TCP会把UDP代表
    5. 为什么TCP不会把取代
    【义务编辑: 赵宁宁 TEL:(010)68476606】

    点赞 0
  • TCP  三次握手  四次挥手
  • 分享:
    大家都在看
    猜你喜欢
  • 订阅专栏+更多

    Kubernetes:21远处完美通关

    Kubernetes:21远处完美通关

    从小白到修神
    共29章 | king584911644

    190人口订阅学习

    Python使用场景实战手册

    Python使用场景实战手册

    Python使用场景实战手册
    共3章 | KaliArch

    122人口订阅学习

    一步到位玩儿透Ansible

    一步到位玩儿透Ansible

    Ansible
    共17章 | 骏马金龙1

    209人口订阅学习

    视频课程+更多

    强哥带你读书docker

    强哥带你读书docker

    教授:周玉强10071人口学习过

    Axure RP9 产品经营原型设计实战课程(借鉴篇)

    Axure RP9 产品经营原型设计实战课程(借鉴篇

    教授:狄睿鑫467人口学习过

    企业级Web Dns构建实战

    企业级Web Dns构建实战

    教授:王硕10215人口学习过

    订阅51CTO邮刊

    点击这里查看样刊

    订阅51CTO邮刊

    51CTO劳务号

    51CTO官微