当前位置: 首页 > news >正文

Linux 环境下 NNG 通讯库:在嵌入式设备上应用

在嵌入式设备开发中,进程间通信(IPC)和网络通信是核心环节。传统的 Socket 编程需要处理复杂的连接管理、协议解析和错误处理,而第三方库如 ZeroMQ 虽简化了流程,却存在依赖重、接口复杂等问题。NNG(Nanomsg Next Generation) 作为 Nanomsg 的继任者,以 “轻量、灵活、无依赖” 为核心优势,

一、NNG 是什么?

NNG 是一款跨平台的消息传递库,专为解决分布式系统中 “进程如何高效交换数据” 的问题而设计。它继承了 Nanomsg 的核心思想,同时优化了 API 设计、性能和可扩展性,尤其适合 Linux 环境下的嵌入式设备、微服务架构和实时数据传输场景。​

与传统方案的对比优势​

  • 对比原生 Socket:无需手动处理 TCP 粘包、UDP 丢包等底层细节,NNG 封装了消息边界处理、连接复用等逻辑,开发者可直接基于 “消息” 而非 “字节流” 编程。​
  • 对比 ZeroMQ:NNG 体积更小(静态库约 500KB)、无外部依赖(不依赖 libzmq 等库),且 API 更简洁(如统一的nng_send/nng_recv接口),编译部署更轻便。​
  • 对比 gRPC:不依赖 HTTP/2 或 Protocol Buffers,适合对性能敏感、需自定义协议的场景,且支持更多通信模式(如 PUB/SUB、BUS)。​

二、NNG 的核心特性

NNG 的灵活性源于其支持的多通信模式,开发者可根据业务场景选择合适的模式,无需重复设计通信逻辑。​

1. 核心技术特性​

  • 轻量级:无守护进程,库文件体积小,内存占用低,适合嵌入式 Linux 系统(如 ARM 架构的物联网设备)。​
  • 异步支持:通过nng_aio接口实现异步 I/O,可在单线程内处理 thousands 级并发连接,避免多线程上下文切换开销。​
  • 跨平台兼容:完美支持 Linux(x86/ARM)、Windows、macOS,代码可无缝移植,尤其适合多端协同的分布式系统。​
  • 内置可靠性:在 UDP 基础上实现了可靠消息传递(如Survey模式的确认机制),平衡性能与可靠性。​

2. 常用通信模式解析​

NNG 的通信模式基于 “套接字类型” 设计,每种模式对应特定的消息交互逻辑:​

模式​

适用场景​

特点​

REQ/REP​

客户端 - 服务器问答(如 API 调用)​

严格请求 - 响应配对,确保消息有序处理​

PUB/SUB​

消息广播(如实时日志、行情推送)​

发布者单向发送,订阅者按需接收,支持主题过滤​

PAIR​

点对点双向通信(如进程间协同)​

全双工通信,适合两个节点长期绑定​

BUS​

多节点对等通信(如分布式集群)​

消息可被所有节点接收,支持多跳转发​

PUSH/PULL​

任务分发(如分布式计算)​

推送端分发任务,拉取端负载均衡接收​

三、Linux 环境下 NNG 实战:从安装到通信​

1. 环境准备与安装​

NNG 在 Linux 下的安装支持源码编译和包管理器两种方式,以 Ubuntu 20.04 为例:​

源码编译(推荐,支持最新版本)​

# 克隆仓库
git clone https://github.com/nanomsg/nng.git
cd nng# 编译(默认生成动态库和静态库)
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j4
sudo make install  # 安装到/usr/local/include和/usr/local/lib

包管理器安装

sudo apt update
sudo apt install libnng-dev  # 包含头文件和共享库

2. 实战案例:PUB/SUB 模式实现实时消息推送​

PUB/SUB(发布 - 订阅)模式适合 “一对多” 的消息分发场景(如实时监控系统中,服务器向多个客户端推送设备状态)。下面实现一个简单的数据推送系统:​

发布端(pub.c):

#include <nng/nng.h>
#include <nng/protocol/pubsub0/pub.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{nng_socket pub_sock;int ret;// 创建PUB类型套接字if ((ret = nng_pub0_open(&pub_sock)) != 0) {fprintf(stderr, "创建套接字失败:%s\n", nng_strerror(ret));return 1;}// 绑定到TCP端口(支持IPC:"ipc:///tmp/temp_pub.ipc")if ((ret = nng_listen(pub_sock, "tcp://0.0.0.0:9000", NULL, 0)) != 0) {fprintf(stderr, "绑定端口失败:%s\n", nng_strerror(ret));nng_close(pub_sock);return 1;}// 模拟温度数据推送float temp = 22.0f;while (1) {char msg[32];sprintf(msg, "temp:%.1f°C", temp + (rand() % 10 - 5) * 0.1); // 随机波动ret = nng_send(pub_sock, msg, strlen(msg), 0);if (ret != 0) {fprintf(stderr, "发送失败:%s\n", nng_strerror(ret));} else {printf("推送:%s\n", msg);}temp += 0.1;sleep(2);}nng_close(pub_sock);return 0;
}

订阅端(sub.c):

#include <nng/nng.h>
#include <nng/protocol/pubsub0/sub.h>
#include <stdio.h>
#include <string.h>int main() 
{nng_socket sub_sock;int ret;// 创建SUB类型套接字if ((ret = nng_sub0_open(&sub_sock)) != 0) {fprintf(stderr, "创建套接字失败:%s\n", nng_strerror(ret));return 1;}// 订阅所有消息(若需过滤,可设置前缀,如nng_setopt(sub_sock, NNG_OPT_SUB_SUBSCRIBE, "temp:", 5))nng_setopt(sub_sock, NNG_OPT_SUB_SUBSCRIBE, "", 0);// 连接发布端if ((ret = nng_dial(sub_sock, "tcp://127.0.0.1:9000", NULL, 0)) != 0) {fprintf(stderr, "连接失败:%s\n", nng_strerror(ret));nng_close(sub_sock);return 1;}// 循环接收消息while (1) {char *msg;size_t len;ret = nng_recv(sub_sock, &msg, &len, NNG_FLAG_ALLOC); // 自动分配内存if (ret != 0) {fprintf(stderr, "接收失败:%s\n", nng_strerror(ret));} else {printf("收到:%.*s\n", (int)len, msg);nng_free(msg, len); // 释放内存}}nng_close(sub_sock);return 0;
}

编译与运行​

# 编译发布端和订阅端(链接nng库)
gcc pub.c -o pub -lnng
gcc sub.c -o sub -lnng# 启动发布端(后台运行)
./pub &# 启动多个订阅端(验证多客户端接收)
./sub
./sub 

四、总结:NNG 在 Linux 生态中的应用价值​

NNG 以 “轻量、灵活、高效” 的特性,无论是嵌入式设备的进程间协同,还是分布式服务的实时数据交换,NNG 都能通过丰富的通信模式和简洁的 API 降低开发成本。​

相比传统方案,NNG 的优势在于:无需关注底层协议细节,专注业务逻辑;无依赖特性简化部署流程,尤其适合资源受限的 Linux 系统;跨平台兼容性保障多端协同的一致性。​

http://www.lryc.cn/news/592135.html

相关文章:

  • iOS WebView 调试实战 全流程排查接口异常 请求丢失与跨域问题
  • 疯狂星期四文案网第11天运营日报
  • 1 初识C++
  • iOS加固工具有哪些?项目场景下的组合策略与实战指南
  • 第一篇htmlcss详细讲解
  • 某邮生活旋转验证码识别
  • Win11安装Docker,并使用Docker安装RabbitMQ
  • 零基础入门:用按键精灵实现视频自动操作(附完整脚本)
  • Docker搭建Elasticsearch和Kibana
  • Python编程进阶知识之第二课学习网络爬虫(selenium)
  • 基于单片机智能充电器系统设计
  • logback日志控制服务器日志输出
  • 【论文精读】基于共识的分布式量子分解算法用于考虑最优传输线切换的安全约束机组组合
  • CursorIP被Ban,设置HttpProxy(亲测可用!!!)
  • 差分隐私机器学习:通过添加噪声让模型更安全,也更智能
  • 【Python】DRF核心组件详解:Mixin与Generic视图
  • Django 实战:I18N 国际化与本地化配置、翻译与切换一步到位
  • Mysql数据库——增删改查CRUD
  • Jfinal+SQLite解决MYSQL迁移表未复制索引问题,完善迁移工具
  • 算法学习笔记:29.拓扑排序——从原理到实战,涵盖 LeetCode 与考研 408 例题
  • hadoop(服务器伪分布式搭建)
  • 瀚高数据库开启Oracle兼容模块
  • Oracle 11g RAC 高可用集群部署最佳实践
  • SQLite / LiteDB 单文件数据库为何“清空表后仍占几 GB”?——原理解析与空间回收实战
  • Golang 中 JSON 和 XML 解析与生成的完全指南
  • sqli-labs靶场通关笔记:第29-31关 HTTP参数污染
  • 配置本地git到gitlab并推送
  • 【LeetCode 热题 100】199. 二叉树的右视图——(解法一)BFS
  • Visual Studio编译WPF项目生成的文件介绍
  • Newline全场景方案闪耀2025中国智慧生活大会