文章插图
ZeroMQ 是一个快速灵活的消息库,用于数据收集和不同编程语言间的数据共享 。• 来源:linux.cn • 作者:Cristiano L. Fontana • 译者:SilentDawn •
(本文字数:12873,阅读时长大约:15 分钟)
作为软件工程师,我有多次在要求完成指定任务时感到浑身一冷的经历 。其中有一次,我必须在一些新的硬件基础设施和云基础设施之间写一个接口,这些硬件需要 C 语言,而云基础设施主要是用 Python 。
实现的方式之一是 用 C 写扩展模块,Python 支持 C 扩展的调用 。快速浏览文档后发现,这需要编写大量的 C 代码 。这样做的话,在有些情况下效果还不错,但不是我喜欢的方式 。另一种方式就是将两个任务放在不同的进程中,并使用 ZeroMQ 消息库 在两者之间交换消息 。
在发现 ZeroMQ 之前,遇到这种类型的情况时,我选择了编写扩展的方式 。这种方式不算太差,但非常费时费力 。如今,为了避免那些问题,我将一个系统细分为独立的进程,通过 通信套接字 发送消息来交换信息 。这样,不同的编程语言可以共存,每个进程也变简单了,同时也容易调试 。
ZeroMQ 提供了一个更简单的过程:
- 编写一小段 C 代码,从硬件读取数据,然后把发现的东西作为消息发送出去 。
- 使用 Python 编写接口,实现新旧基础设施之间的对接 。
准备本教程中,需要:
- 一个 C 编译器(例如 GCC 或 Clang )
- libzmq 库
- Python 3
- ZeroMQ 的 Python 封装
$ dnf install clang zeromq zeromq-devel python3 python3-zmq
Debian 和 Ubuntu 系统上的安装方法:$ apt-get install clang libzmq5 libzmq3-dev python3 python3-zmq
如果有问题,参考对应项目的安装指南(上面附有链接) 。编写硬件接口库因为这里针对的是个设想的场景,本教程虚构了包含两个函数的操作库:
- fancyhw_init() 用来初始化(设想的)硬件
- fancyhw_read_val() 用于返回从硬件读取的数据
#ifndef LIBFANCYHW_H#define LIBFANCYHW_H#include <stdlib.h>#include <stdint.h>// This is the fictitious hardware interfacing libraryvoid fancyhw_init(unsigned int init_param){ srand(init_param);}int16_t fancyhw_read_val(void){ return (int16_t)rand();}#endif
这个库可以模拟你要在不同语言实现的组件间交换的数据,中间有个随机数发生器 。设计 C 接口下面从包含管理数据传输的库开始,逐步实现 C 接口 。
需要的库
开始先加载必要的库(每个库的作用见代码注释):
// For printf()#include <stdio.h>// For EXIT_*#include <stdlib.h>// For memcpy()#include <string.h>// For sleep()#include <unistd.h>#include <zmq.h>#include "libfancyhw.h"
必要的参数定义 main 函数和后续过程中必要的参数:
int main(void){ const unsigned int INIT_PARAM = 12345; const unsigned int REPETITIONS = 10; const unsigned int PACKET_SIZE = 16; const char *TOPIC = "fancyhw_data"; ...
初始化所有的库都需要初始化 。虚构的那个只需要一个参数:
fancyhw_init(INIT_PARAM);
ZeroMQ 库需要实打实的初始化 。首先,定义对象 context,它是用来管理全部的套接字的:void *context = zmq_ctx_new();if (!context){ printf("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %sn", zmq_strerror(errno)); return EXIT_FAILURE;}
之后定义用来发送数据的套接字 。ZeroMQ 支持若干种套接字,各有其用 。使用 publish 套接字(也叫 PUB 套接字),可以复制消息并分发到多个接收端 。这使得你可以让多个接收端接收同一个消息 。没有接收者的消息将被丢弃(即不会入消息队列) 。用法如下:void *data_socket = zmq_socket(context, ZMQ_PUB);
套接字需要绑定到一个具体的地址,这样客户端就知道要连接哪里了 。本例中,使用了 TCP 传输层 (当然也有 其它选项,但 TCP 是不错的默认选择):const int rb = zmq_bind(data_socket, "tcp://*:5555");if (rb != 0){ printf("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %sn", zmq_strerror(errno)); return EXIT_FAILURE;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 6个顶级可视化Python库
- 你平时是怎么管理 Docker 容器的?还在使用一大堆的窗口和命令吗
- |还在流通使用的5角纸币,单张价值22000元,你有吗?
- 龙利鱼|夏季能不能使用面霜?只要用对,效果就会翻倍
- 使用 PowerDNS 轻松配置 DNS 名称服务器
- 如何消息队列的数据积压问题
- 什么是Java可变参数列表?怎么和重载机制配合使用?
- 小米|小米Civi 1S用上骁龙778G Plus!美女产品经理:日常使用非常省心
- 喝茶黑色时段,宋代饮茶为什么流行使用黑色的建盏
- 第一颗使用望远镜发现的行星 一艘飞船飞向黑洞,远方观测者