jtbldrco/LWComCon
GitHub: jtbldrco/LWComCon
一个基于 TCP 网络的轻量级 C++/Java 命令与控制框架,通过点对点通信实现跨平台的进程间管理与有序关闭等设计模式。
Stars: 1 | Forks: 1
# *轻量级* C++ 命令/控制 [#LWComCon]
## 基于网络的、多进程、多线程的 C++ 命令/控制框架(在 Java 中展示了类似的功能)
**MIT 许可证 -- 版权所有 2018-2023 iWay Technology LLC -- Boulder, Colorado USA**
(*部分内容源自或改编自 iWay Technology 此前在开源许可证下发布的工作*)
### C++ 框架/设计模式亮点:
1. 点对点进程间通信处理器
2. ThreadWorker 设计模式
3. 对内存管理友好的、线程安全的、基于指针的 STL 集合设计模式(详见下文)
多线程、网络 socket、多进程……这*哪里轻量级*了?
嗯,首先,你不会在中间发现一个需要为其分配机器资源、启动、配置、集成、更新和管理的第三方 broker。相反,**所有的通信实际上都是点对点的**,并通过一种简单的 TCP 网络消息模型(具有用户定义的语义)和可选的 acks 来实现。我的发现是,许多场景不需要,并且/或者无法承载或处理 HA 故障转移、保证交付、路由魔法等。
无论你是在 Kubernetes 容器还是无线路由器中运行,通常——简单即是更好。
此外,特定于操作系统的信号机制(例如 Linux 的 Signal Handling)显然不可移植,在多主机架构中也不是特别有用。**LWComCon 是完全可移植的**,可以运行在任何具备 TCP 网络和线程功能的操作系统上——从桌面无线路由器到云环境。
本代码库包含用于介绍和演示基于 C++(在 Java 中也有类似但精简的展示)的材料,这是一个基于 TCP 网络、支持多处理和多线程的命令与控制框架,它脱胎于经过实战检验的过往工作:*有序关闭设计模式* (OSP)。
其中包含了众多额外的实用*设计模式*,例如 -
- **ThreadedWorker 设计模式**(作为 C++ 类实现),它提供了一种简单易用的多线程编码方法,明确了 *creator*(创建者)线程和 *created*(被创建)线程之间的分工,以及用于启动、操作和关闭的使用模式[即“内存管理的便捷性”],
- 一个线程安全的、基于指针的消息队列——在此处以 **C++ 模板类 ThreadSafeMsgPtrQueue** 的形式出现——它演示了软件的*资源获取即初始化* (RAII),并让标准模板库集合的线程安全使用变得微不足道(可以想象成*透明的*),(同时也为*基于指针的 C++ 集合*的安全、负责任的管理定义了一种模式),
- 一个**更高层的消息通信处理器设计模式**(类 MsgCommHdlr),它结合了上述两个类,提供了将多个网络通信 endpoint 快速集成到更大上下文中的能力,如本代码库项目 [lwcomcon_full](./c++/lwcomcon_full) 中所示。
- Linux **rslog 日志记录**技术和工具,以及
- 其他**用于简化 C++ 多线程和网络编程**、测试和故障排除的工具。
## C++ 用例示例:轻量级命令与控制的完整(且简单的)实现和演示
此子目录项目在一个工作示例中使用了上述所有组件,该示例旨在从两个控制台窗口运行以演示其动态过程。
有关 C++ 用例的完整详细信息,请参阅 [./c++/lwcomcon_full](./c++/lwcomcon_full)。
### Java 用例示例:有序关闭模式
这些 Java 示例与上述 C++ 示例类似,但在范围上更简单(更容易理解),并且除了有序关闭模式的使用场景外,并未涉及 LWComCon 的其他内容。
## LWComCon 详情
轻量级命令与控制框架使用基于 TCP/IP 的网络通信,允许具有任意功能的正在运行的服务的一个*listener thread*进行监控,并*在它自己选择的时间*响应任何命令/控制消息。作为一个简单的例子,考虑发送一个关闭消息来执行关闭(详见下文)。如果/当收到这样的请求时,服务将能够在进行任何响应之前完成其排队或启动的任何关键工作(由服务自行决定)——例如,进入最终导致终止的关闭过程。
这种模式有多个优点,首先是正在运行的服务可以决定何时*以及如何*处理该请求。这可能包括将那些已接收但尚未完成的任务与消息 broker 一起重新排队。或者,它也可能包括在终止之前完成这些任务。任何挂起的 I/O 操作都可以被正确地刷新和关闭,并且任何其他相关服务也可以同样地被通知其挂起的操作或状态更改。
其他优点包括支持从远程、多个来源进行控制。具体来说,这种模式与 Unix 信号处理(例如 SIGKILL 或 SIGTERM)有何不同?首先,这种模式是与操作系统无关的。其次,即使目标服务的主机不允许控制台访问,它也允许对目标服务进行控制(这在开发/测试中问题不大;但在生产环境中问题较大——特别是想象一下在 Kubernetes 中运行的服务……)。
无法访问?没问题。相反,可以通过网络从防火墙内部的任何(或者每一台?)机器向目标主机发送任何消息(**而且,现在你可能在想,*这难道不能用于* shutdown *信号通知之外的更多用途吗?*——当然可以!**)。
因此,使用这种模式,shutdown 消息*可以*包含任何级别的细微差别(超越了 Java 示例中实现的简单情况“尽可能方便时关闭”——再说一次,实际上*任何*消息语义都可以,甚至是一个完整的控制协议)。并且通过打开的双向 socket,可以返回任何确认信息——例如,甚至可以是对完成时间的估计。
更多扩展语义的一些例子可能是“关闭一个 producer 线程”,或者“添加一个 consumer 线程”等。
除了这些之外,使用这种模式,可以使用任何端口(适应防火墙和隧道因素);它不需要更高级别的协议(HTTP 等),这使得它*非常*轻量级(想象一下*嵌入式*设备——单线程上的单个 socket,对比某个拖入整个 Python runtime 环境的嵌入式 http 服务器,或者甚至更重的、与必须被启动和维护的中间人 broker 进程耦合的嵌入式 message-bus 客户端[还需要为 HA 等进行配置?])。
如果需要/要求,有序关闭模式可扩展至 SSL(此处未展示)。
最后,从单独进程发起的客户端消息发送允许与标准 cron 作业进行快速、简单的集成。甚至 telnet 也能与这种设计模式一起工作。
### OSP 的要素
有序关闭模式依赖于以下基本概念 -
- 多线程,或多进程(根据需要/要求)
- Socket 通信(具有任何消息语义)
要了解 OSP 实现(基础版和完整版——见下文)的操作和使用,必须熟悉上述两个概念。
#### 概念背景与介绍
正如附图所示,OSP 在上述概念周围包裹了额外的逻辑和处理,利用了它们的潜力。这可能使得一些人在没有更多最新资料的情况下,难以修改、增强或重构 OSP 架构。
因此,作为入门,本文包含了这两个基础概念——多线程和 socket 通信——的最基础示例。请参阅 -
- 基础多线程示例:[mt_basic](./mt_basic)
- 基础的服务器-客户端 socket 通信示例:[socket_basic](./socket_basic)
### 有序关闭模式实现 - 基础版与完整版
我们提供了两个完全可运行的实现——基础版和完整版。这两个实现都使用以下手段来通用地演示 OSP -
- 线程休眠行为,用于模拟花费在“真实的、不可中断的工作”上的时间流逝。
- 一个内部计数器,如果没有发送终止消息,该计数器最终将终止服务(用以在任何情况下说明服务的关闭行为)。
### OSP 基础实现
基础实现包含以下特性 -
- 使用一个单独的线程来监听和管理终止消息的接收。这被封装在一个派生自 Thread 的单独类中。
- 在服务进程中使用一个 listener socket,它在整个等待终止消息的过程中保持打开状态。
- 一个在服务中运行的“不可中断的工作”循环,定期检查终止消息是否到达。
### LWComCon 完整实现
完整实现采用了基础实现的所有要素,并添加了以下内容 -
- 两个执行服务“不可中断工作”的独立线程工作类实例,被允许在适当的时候检查终止条件(在进程内部,而不是跨网络)是否存在。
- 对终止 listener socket 管理的增强,以*抵挡*在该 socket 上接收到的格式错误或完全随机的消息。
- 对终止发送方逻辑的增强,允许从运行目标服务的主机之外的其他主机发送终止消息。为了进行测试,该逻辑仍然支持将 'localhost' 作为终止消息的目标。
## 构建和运行 LWComCon 示例
所有示例仅限命令行——不涉及任何 GUI 内容。这既是故意的,也是实用的——这些是基于服务器的概念,而不是基于桌面的(尽管它们*可以*在那里使用)。要运行某些示例,只需要一个控制台窗口;对于其他示例,必须使用第二个控制台窗口(例如,在另一个窗口中运行的服务上执行停止脚本)。
所有示例都已在 Ubuntu(特别是 Ubuntu-server 17.10)上构建并经过测试,尽管并未使用特定于该发行版的功能。对于 Java 部分,即使是较旧的 JDK 版本也能工作,但测试是使用 Java 1.7 到 Java 9 完成的。
LWComCon 代码库的所有元素都包含可运行的版本(mt、socket、basic、full)。每一个都有构建脚本或 makefile。为您的环境安装合适软件的详细信息超出了这项工作的范围,但是有无数的来源可以提供相关信息,并且我在下面添加了一些从我的命令行历史记录中提取的安装步骤。
简而言之,您的机器上需要 C++ 或 Java 开发工具才能运行这些示例。你可以从 GitHub 下载 tar 文件,或者 clone 该代码库(首选,且易如反掌)。请看这里 -
As noted throughout, an MIT Open Source License has been attached to everything - it's short, direct, complete, and quite permissive, but PLEASE READ THE LICENSE (appearing below) if you are unfamiliar with its permission grants and restrictions. 欢迎通过 jt [at] iwaytechnology [dot] com 发表评论(并提出简短的问题)。 ### 支持软件安装提示 这并不打算成为构建机器设置的教程,但以下是准备 Ubuntu-server 以创建这些作品所采取的步骤。请注意,并非所有这些工具都是必需的(特别是 ubuntu-desktop),但其中许多可能在过程中被附带使用。 #### 一些 Ubuntu 工具 我发现 Ubuntu 桌面版安装(见下文)轻量且安装快速,因为它会避免下载“办公类”软件以及其他对仅用于开发的机器来说多余的东西。我不确定是否必须安装 gnome-terminal,但也装上了;我相信 Firefox 最初是没有的;openssh-server 允许你通过 ssh 连接到机器(需要进行一些简单的配置——请上网查找提示——你需要找的是 /etc/ssh/sshd_config ……如果该文件缺失,说明该软件包尚未安装。 ``` $ sudo apt install --no-install-recommends ubuntu-desktop $ sudo apt install gnome-terminal $ sudo apt install firefox $ sudo apt install openssh-server $ sudo apt install git-core ``` #### C++ 在我的机器上安装的许多开发包可能并没有在 OSP 代码中实际使用。从这里开始,看看你还需要什么来构建和运行示例代码。这应该包括 gcc/g++、make、库和头文件。 ``` $ sudo apt-get install build-essential ``` #### Java ``` $ sudo apt install openjdk-21-jdk - or - $ sudo add-apt-repository ppa:linuxuprising/java $ sudo apt update $ sudo apt install oracle-java21-installer ```
**MIT 许可证 -- 版权所有 2018-2023 iWay Technology LLC -- Boulder, Colorado USA**
特此免费授予任何获得本软件及相关文档文件(“软件”)副本的人,不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向其提供软件的人员在符合以下条件的情况下这样做:
上述版权声明和本整个许可声明,包括上下段落,应包含在软件的所有副本或实质性部分中。
本软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于适销性、特定用途的适用性和非侵权保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他行为中,由本软件或本软件的使用或其他交易引起的或与之相关的责任。
(*部分内容源自或改编自 iWay Technology 此前在开源许可证下发布的工作*)
### C++ 框架/设计模式亮点:
1. 点对点进程间通信处理器
2. ThreadWorker 设计模式
3. 对内存管理友好的、线程安全的、基于指针的 STL 集合设计模式(详见下文)
多线程、网络 socket、多进程……这*哪里轻量级*了?
嗯,首先,你不会在中间发现一个需要为其分配机器资源、启动、配置、集成、更新和管理的第三方 broker。相反,**所有的通信实际上都是点对点的**,并通过一种简单的 TCP 网络消息模型(具有用户定义的语义)和可选的 acks 来实现。我的发现是,许多场景不需要,并且/或者无法承载或处理 HA 故障转移、保证交付、路由魔法等。
无论你是在 Kubernetes 容器还是无线路由器中运行,通常——简单即是更好。
此外,特定于操作系统的信号机制(例如 Linux 的 Signal Handling)显然不可移植,在多主机架构中也不是特别有用。**LWComCon 是完全可移植的**,可以运行在任何具备 TCP 网络和线程功能的操作系统上——从桌面无线路由器到云环境。
本代码库包含用于介绍和演示基于 C++(在 Java 中也有类似但精简的展示)的材料,这是一个基于 TCP 网络、支持多处理和多线程的命令与控制框架,它脱胎于经过实战检验的过往工作:*有序关闭设计模式* (OSP)。
其中包含了众多额外的实用*设计模式*,例如 -
- **ThreadedWorker 设计模式**(作为 C++ 类实现),它提供了一种简单易用的多线程编码方法,明确了 *creator*(创建者)线程和 *created*(被创建)线程之间的分工,以及用于启动、操作和关闭的使用模式[即“内存管理的便捷性”],
- 一个线程安全的、基于指针的消息队列——在此处以 **C++ 模板类 ThreadSafeMsgPtrQueue** 的形式出现——它演示了软件的*资源获取即初始化* (RAII),并让标准模板库集合的线程安全使用变得微不足道(可以想象成*透明的*),(同时也为*基于指针的 C++ 集合*的安全、负责任的管理定义了一种模式),
- 一个**更高层的消息通信处理器设计模式**(类 MsgCommHdlr),它结合了上述两个类,提供了将多个网络通信 endpoint 快速集成到更大上下文中的能力,如本代码库项目 [lwcomcon_full](./c++/lwcomcon_full) 中所示。
- Linux **rslog 日志记录**技术和工具,以及
- 其他**用于简化 C++ 多线程和网络编程**、测试和故障排除的工具。
## C++ 用例示例:轻量级命令与控制的完整(且简单的)实现和演示
此子目录项目在一个工作示例中使用了上述所有组件,该示例旨在从两个控制台窗口运行以演示其动态过程。
有关 C++ 用例的完整详细信息,请参阅 [./c++/lwcomcon_full](./c++/lwcomcon_full)。
### Java 用例示例:有序关闭模式
这些 Java 示例与上述 C++ 示例类似,但在范围上更简单(更容易理解),并且除了有序关闭模式的使用场景外,并未涉及 LWComCon 的其他内容。
## LWComCon 详情
轻量级命令与控制框架使用基于 TCP/IP 的网络通信,允许具有任意功能的正在运行的服务的一个*listener thread*进行监控,并*在它自己选择的时间*响应任何命令/控制消息。作为一个简单的例子,考虑发送一个关闭消息来执行关闭(详见下文)。如果/当收到这样的请求时,服务将能够在进行任何响应之前完成其排队或启动的任何关键工作(由服务自行决定)——例如,进入最终导致终止的关闭过程。
这种模式有多个优点,首先是正在运行的服务可以决定何时*以及如何*处理该请求。这可能包括将那些已接收但尚未完成的任务与消息 broker 一起重新排队。或者,它也可能包括在终止之前完成这些任务。任何挂起的 I/O 操作都可以被正确地刷新和关闭,并且任何其他相关服务也可以同样地被通知其挂起的操作或状态更改。
其他优点包括支持从远程、多个来源进行控制。具体来说,这种模式与 Unix 信号处理(例如 SIGKILL 或 SIGTERM)有何不同?首先,这种模式是与操作系统无关的。其次,即使目标服务的主机不允许控制台访问,它也允许对目标服务进行控制(这在开发/测试中问题不大;但在生产环境中问题较大——特别是想象一下在 Kubernetes 中运行的服务……)。
无法访问?没问题。相反,可以通过网络从防火墙内部的任何(或者每一台?)机器向目标主机发送任何消息(**而且,现在你可能在想,*这难道不能用于* shutdown *信号通知之外的更多用途吗?*——当然可以!**)。
因此,使用这种模式,shutdown 消息*可以*包含任何级别的细微差别(超越了 Java 示例中实现的简单情况“尽可能方便时关闭”——再说一次,实际上*任何*消息语义都可以,甚至是一个完整的控制协议)。并且通过打开的双向 socket,可以返回任何确认信息——例如,甚至可以是对完成时间的估计。
更多扩展语义的一些例子可能是“关闭一个 producer 线程”,或者“添加一个 consumer 线程”等。
除了这些之外,使用这种模式,可以使用任何端口(适应防火墙和隧道因素);它不需要更高级别的协议(HTTP 等),这使得它*非常*轻量级(想象一下*嵌入式*设备——单线程上的单个 socket,对比某个拖入整个 Python runtime 环境的嵌入式 http 服务器,或者甚至更重的、与必须被启动和维护的中间人 broker 进程耦合的嵌入式 message-bus 客户端[还需要为 HA 等进行配置?])。
如果需要/要求,有序关闭模式可扩展至 SSL(此处未展示)。
最后,从单独进程发起的客户端消息发送允许与标准 cron 作业进行快速、简单的集成。甚至 telnet 也能与这种设计模式一起工作。
### OSP 的要素
有序关闭模式依赖于以下基本概念 -
- 多线程,或多进程(根据需要/要求)
- Socket 通信(具有任何消息语义)
要了解 OSP 实现(基础版和完整版——见下文)的操作和使用,必须熟悉上述两个概念。
#### 概念背景与介绍
正如附图所示,OSP 在上述概念周围包裹了额外的逻辑和处理,利用了它们的潜力。这可能使得一些人在没有更多最新资料的情况下,难以修改、增强或重构 OSP 架构。
因此,作为入门,本文包含了这两个基础概念——多线程和 socket 通信——的最基础示例。请参阅 -
- 基础多线程示例:[mt_basic](./mt_basic)
- 基础的服务器-客户端 socket 通信示例:[socket_basic](./socket_basic)
### 有序关闭模式实现 - 基础版与完整版
我们提供了两个完全可运行的实现——基础版和完整版。这两个实现都使用以下手段来通用地演示 OSP -
- 线程休眠行为,用于模拟花费在“真实的、不可中断的工作”上的时间流逝。
- 一个内部计数器,如果没有发送终止消息,该计数器最终将终止服务(用以在任何情况下说明服务的关闭行为)。
### OSP 基础实现
基础实现包含以下特性 -
- 使用一个单独的线程来监听和管理终止消息的接收。这被封装在一个派生自 Thread 的单独类中。
- 在服务进程中使用一个 listener socket,它在整个等待终止消息的过程中保持打开状态。
- 一个在服务中运行的“不可中断的工作”循环,定期检查终止消息是否到达。
### LWComCon 完整实现
完整实现采用了基础实现的所有要素,并添加了以下内容 -
- 两个执行服务“不可中断工作”的独立线程工作类实例,被允许在适当的时候检查终止条件(在进程内部,而不是跨网络)是否存在。
- 对终止 listener socket 管理的增强,以*抵挡*在该 socket 上接收到的格式错误或完全随机的消息。
- 对终止发送方逻辑的增强,允许从运行目标服务的主机之外的其他主机发送终止消息。为了进行测试,该逻辑仍然支持将 'localhost' 作为终止消息的目标。
## 构建和运行 LWComCon 示例
所有示例仅限命令行——不涉及任何 GUI 内容。这既是故意的,也是实用的——这些是基于服务器的概念,而不是基于桌面的(尽管它们*可以*在那里使用)。要运行某些示例,只需要一个控制台窗口;对于其他示例,必须使用第二个控制台窗口(例如,在另一个窗口中运行的服务上执行停止脚本)。
所有示例都已在 Ubuntu(特别是 Ubuntu-server 17.10)上构建并经过测试,尽管并未使用特定于该发行版的功能。对于 Java 部分,即使是较旧的 JDK 版本也能工作,但测试是使用 Java 1.7 到 Java 9 完成的。
LWComCon 代码库的所有元素都包含可运行的版本(mt、socket、basic、full)。每一个都有构建脚本或 makefile。为您的环境安装合适软件的详细信息超出了这项工作的范围,但是有无数的来源可以提供相关信息,并且我在下面添加了一些从我的命令行历史记录中提取的安装步骤。
简而言之,您的机器上需要 C++ 或 Java 开发工具才能运行这些示例。你可以从 GitHub 下载 tar 文件,或者 clone 该代码库(首选,且易如反掌)。请看这里 -
~$ mkdir dev
~$ cd dev
~/dev$ git clone https://github.com/jtbldrco/LWComCon.git
As noted throughout, an MIT Open Source License has been attached to everything - it's short, direct, complete, and quite permissive, but PLEASE READ THE LICENSE (appearing below) if you are unfamiliar with its permission grants and restrictions. 欢迎通过 jt [at] iwaytechnology [dot] com 发表评论(并提出简短的问题)。 ### 支持软件安装提示 这并不打算成为构建机器设置的教程,但以下是准备 Ubuntu-server 以创建这些作品所采取的步骤。请注意,并非所有这些工具都是必需的(特别是 ubuntu-desktop),但其中许多可能在过程中被附带使用。 #### 一些 Ubuntu 工具 我发现 Ubuntu 桌面版安装(见下文)轻量且安装快速,因为它会避免下载“办公类”软件以及其他对仅用于开发的机器来说多余的东西。我不确定是否必须安装 gnome-terminal,但也装上了;我相信 Firefox 最初是没有的;openssh-server 允许你通过 ssh 连接到机器(需要进行一些简单的配置——请上网查找提示——你需要找的是 /etc/ssh/sshd_config ……如果该文件缺失,说明该软件包尚未安装。 ``` $ sudo apt install --no-install-recommends ubuntu-desktop $ sudo apt install gnome-terminal $ sudo apt install firefox $ sudo apt install openssh-server $ sudo apt install git-core ``` #### C++ 在我的机器上安装的许多开发包可能并没有在 OSP 代码中实际使用。从这里开始,看看你还需要什么来构建和运行示例代码。这应该包括 gcc/g++、make、库和头文件。 ``` $ sudo apt-get install build-essential ``` #### Java ``` $ sudo apt install openjdk-21-jdk - or - $ sudo add-apt-repository ppa:linuxuprising/java $ sudo apt update $ sudo apt install oracle-java21-installer ```
**MIT 许可证 -- 版权所有 2018-2023 iWay Technology LLC -- Boulder, Colorado USA**
特此免费授予任何获得本软件及相关文档文件(“软件”)副本的人,不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向其提供软件的人员在符合以下条件的情况下这样做:
上述版权声明和本整个许可声明,包括上下段落,应包含在软件的所有副本或实质性部分中。
本软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于适销性、特定用途的适用性和非侵权保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他行为中,由本软件或本软件的使用或其他交易引起的或与之相关的责任。标签:C++, IP 地址批量处理, JS文件枚举, 命令与控制框架, 数据擦除, 网络通信, 设计模式, 进程间通信