使用 SCTP 进行故障检测和关联拆卸

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

概述

上一篇文章 中,我们回顾了 SCTP 协议的本质是如何工作的——用户数据传输。现在是时候看看一些故障检测过程,最后看看 SCTP 关联是如何关闭的。这两个主题都将在本文中讨论。错误检测程序在 第 8 节 中指定,标题为“故障管理”,但在这篇文章中我将主要讨论心跳。其他故障检测机制将进行简要描述,因此如果您想了解更多有关特定机制的信息,请阅读规范的相应部分(每个部分都提供超链接)。关联拆除在 第 9 节 “关联终止”中指定。

故障检测

还记得 SCTP 具有称为多宿主的功能吗?我在 关于关联初始化的帖子 中提到了它。简而言之,它提供了为关联中的每个端点使用多个 IP 地址的选项。此选项使 SCTP 中的错误处理更加奇特。它有两个主要方面——端点和路径故障检测。如果您对这个主题感兴趣,可以查看

端点故障检测

每个端点都保留对其对等端的连续重传计数。如果该值超过“Association.Max.Retrans”参数,则必须关闭关联。有关详细信息,请查看 第 8.1 节

路径故障检测

在多宿主场景中,每个端点都会为到其对等端的每条路径保留错误计数。当错误计数超过“Path.Max.Retrans”参数值时,端点应认为目标地址无效。 SCTP 堆栈还应通知用户有关对等地址不可用的信息。有关如何检测错误、实施说明和配置提示的更多详细信息,请查看 第 8.2 节 ,其中介绍了路径故障检测。

路径心跳

当建立 SCTP 关联时,协议栈应该监视其对等方的每个空闲 IP 地址。如果没有来自/去往该地址的流量,SCTP 堆栈应该将 HEARTBEAT 块发送到空闲 IP 地址。接收方应使用 HEARTBEAT ACK 数据块进行响应。此操作仅在关联建立时执行。 8.3 节 详细描述了路径心跳。

心跳块

您可以在图 1 中看到示例 HEARTBEAT 块。它在 第 3.3.5 节 中进行了描述。它的块类型是4,它有一个可变长度的参数——心跳信息。它包含发送方特定信息,通常是发送块的时间。接收方不需要理解此信息 - 它只是与 HEARTBEAT ACK 块一起发回。

图 1: heartbeat.pcapng

心跳确认块

示例 HEARTBEAT ACK 块如图 2 所示。它在 第 3.3.6 节 中指定。它也只有一个可变长度参数——心跳信息,在心跳块中接收。

图 2: heartbeat-ack.pcapng

整个踪迹

上面的块是从一个虚拟的客户端-服务器程序中提取的,该程序通过网络发送一些随机数据。您可以从 此处 下载整个跟踪。

协会拆解

每个关联在不再使用或发生任何严重错误时终止。有两种方法可以实现这一点 - 通过关闭或通过中止。第一个被认为是优雅终止。传输任何未决数据,并且两个对等方都认为关联已终止。后者是错误终止,所有未发送的用户数据都将被丢弃。

协会中止

关联被 ABORT 块中止。它不能与任何数据块捆绑在一起。接收方应检查公共标头中的验证标签是否与自己的标签匹配。如果是 - 块被接受,关联被破坏并通知上层。在图 3 中,您可以看到一个 ABORT 块。它在规范的 第 3.3.7 节 中进行了描述。该块只有一个可选参数——error cause,指定中止的原因。图 3 中 ABORT 块中的错误原因是 0x000c,这是用户发起的中止。所有可能的值都列在 第 3.3.10 节 中。

图 3: abort.pcapng

ABORT 块在块标志中有一个保留位——T 位。这是最后一个(第 8 个)。将其设置为零表示发送方已在公共标头中填写了验证标记。我们已经简要讨论了这个值是如何处理的。如果您想了解更多相关信息,请查看 第 8.5.1 节

您可以下载图 3 中包含 ABORT 块的 跟踪

协会关闭

关联关闭由其中一个 SCTP 用户发起。这表明不再需要该关联,需要优雅地释放它。该过程如图 4 所示。我们将回顾简化的停机案例。我们不会涵盖诸如超时或意外消息之类的事情。如果这对您很重要,请查看 第 9.2 节 ,其中详细介绍了关联关闭程序。

图 4:协会关闭

在图 4 中,我们假设关联已经建立并且当前处于数据传输阶段。此时,主机 A 上的用户希望解除关联,并向 SCTP 堆栈发出关闭请求。堆栈 A 进入 SHUTDOWN-PENDING 状态,并停止接受来自用户的数据。端点保持此状态,直到它发送所有未决数据块(在关闭启动之前被接受)。当它们被传输时,A 进入 SHUTDOWN 状态并向 B 发送 SHUTDOWN 数据块。该数据块包括它迄今为止从 B 接收到的最后一个顺序 TSN。在此状态下,A 可能仍会从 B 接收数据数据块,并且它应该通过确认相应地采取行动收到 TSN 并报告差距/重复。目的是让 B 在接收到 SHUTDOWN 块之前发送它从用户那里接受的所有数据。

一旦 B 收到 SHUTDOWN 块,它就会进入 SHUTDOWN-RECEIVED 状态并停止接受来自其用户的数据。 B 还检查在 SHUTDOWN 块中收到的 TSN,并验证 A 是否收到了所有未完成的数据。如果有未发送/未收到的数据块,B 将继续其正常操作,直到发送完所有数据。数据传输完毕后,B向A发送SHUTDOWN ACK chunk,进入SHUTDOWN-ACK-SENT状态。这是对 A 可以解除关联的确认。此时 A 清除所有关于关联的记录并发送 SHUTDOWN COMPLETE。当 B 收到块时,它也清除关联。

再次请注意,这是一个非常简单的关机程序版本。上面的描述足以从用户的角度理解关联终止是如何工作的。但是,如果您正在开发自定义 SCTP 堆栈(例如),请确保您已阅读并充分理解 第 9.2 节

现在让我们看一下 SHUTDOWN、SHUTDOWN ACK 和 SHUTDOWN COMPLETE 块。

关闭块

图 5 中有一个示例 SHUTDOWN 块。它只有一个参数 - Cumulative TSN Ack。如前一节所述,它包含最后一个数据块的 TSN,接收时没有任何间隙。 SHUTDOWN 块在 第 3.3.8 节 中指定。

图 5: shutdown.pcapng

SHUTDOWN ACK 和 SHUTDOWN COMPLETE 块

两个块都没有参数。我们已经介绍了它们的用途,所以我在这里只提供示例。图 6 显示了在 第 3.3.9 节 中指定的 SHUTDOWN ACK 块。 SHUTDOWN COMPLETE 块如图 7 所示,您可以在 第 3.3.13 节 中找到它的规范。

图 6: shutdown_ack.pcapng

图 7: shutdown_complete.pcapng

最后的话

在这四篇文章中,我们介绍了一些基本的 SCTP 术语、消息的编码方式、关联的创建和销毁方式以及数据传输的工作方式。我希望你喜欢阅读并且你学到了一些新东西。有些主题是我故意跳过的。其中大部分对普通 SCTP 用户没有用。一个例外是多宿主。这是 SCTP 的杀手级特性之一,我没有介绍它,我建议您自己阅读它。 第 6.4 节 应该是阅读本文的良好开端,但要注意多宿主散布在整个规范中。我计划在未来专门写一篇关于它的文章,但现在你只能靠自己了。

这些帖子中的几乎所有示例都是从测试 SCTP 会话中提取的,该会话是使用虚拟客户端-服务器应用程序创建的。我在所有帖子中都提供了指向单个消息的链接,但如果您想查看整个图片,可以 从此链接 获取踪迹。