用如下命令编译:
$ clang -std=c99 -I. hw_interface.c -lzmq -o hw_interface如果没有编译错误,你就可以运行这个接口了 。贴心的是,ZeroMQ PUB 套接字可以在没有任何应用发送或接受数据的状态下运行,这简化了使用复杂度,因为这样不限制进程启动的次序 。
运行该接口:
$ ./hw_interfaceTopic: fancyhw_data; topic size: 12; Envelope size: 45Read 16 data valuesMessage sent; i: 0, topic: fancyhw_dataRead 16 data valuesMessage sent; i: 1, topic: fancyhw_dataRead 16 data values......输出显示数据已经通过 ZeroMQ 完成发送,现在要做的是让一个程序去读数据 。
编写 Python 数据处理器现在已经准备好从 C 程序向 Python 应用传送数据了 。
库
需要两个库帮助实现数据传输 。首先是 ZeroMQ 的 Python 封装:
$ python3 -m pip install zmq另一个就是 struct 库,用于解码二进制数据 。这个库是 Python 标准库的一部分,所以不需要使用 pip 命令安装 。
Python 程序的第一部分是导入这些库:
import zmqimport struct重要参数
使用 ZeroMQ 时,只能向常量 TOPIC 定义相同的接收端发送消息:
topic = "fancyhw_data".encode('ascii')print("Reading messages with topic: {}".format(topic))初始化
下一步,初始化上下文和套接字 。使用 subscribe 套接字(也称为 SUB 套接字),它是 PUB 套接字的天生伴侣 。这个套接字发送时也需要匹配主题 。
with zmq.Context() as context: socket = context.socket(zmq.SUB) socket.connect("tcp://127.0.0.1:5555") socket.setsockopt(zmq.SUBSCRIBE, topic) i = 0 ...接收消息
启动一个无限循环,等待接收发送到 SUB 套接字的新消息 。这个循环会在你按下 Ctrl+C 组合键或者内部发生错误时终止:
try: while True: ... # we will fill this in next except KeyboardInterrupt: socket.close() except Exception as error: print("ERROR: {}".format(error)) socket.close()这个循环等待 recv() 方法获取的新消息,然后将接收到的内容从第一个空格字符处分割开,从而得到主题:
binary_topic, data_buffer = socket.recv().split(b' ', 1)解码消息
Python 此时尚不知道主题是个字符串,使用标准 ASCII 编解码器进行解码:
topic = binary_topic.decode(encoding = 'ascii')print("Message {:d}:".format(i))print("ttopic: '{}'".format(topic))下一步就是使用 struct 库读取二进制数据,它可以将二进制数据段转换为明确的数值 。首先,计算数据包中数值的组数 。本例中使用的 16 个位的有符号整数对应的是 struct 格式字符 中的 h:
packet_size = len(data_buffer) // struct.calcsize("h")print("tpacket size: {:d}".format(packet_size))知道数据包中有多少组数据后,就可以通过构建一个包含数据组数和数据类型的字符串,来定义格式了(比如“16h”):
struct_format = "{:d}h".format(packet_size)将二进制数据串转换为可直接打印的一系列数字:
data = struct.unpack(struct_format, data_buffer)print("tdata: {}".format(data))完整 Python 代码
下面是 Python 实现的完整的接收端:
#! /usr/bin/env python3import zmqimport structtopic = "fancyhw_data".encode('ascii')print("Reading messages with topic: {}".format(topic))with zmq.Context() as context: socket = context.socket(zmq.SUB) socket.connect("tcp://127.0.0.1:5555") socket.setsockopt(zmq.SUBSCRIBE, topic) i = 0 try: while True: binary_topic, data_buffer = socket.recv().split(b' ', 1) topic = binary_topic.decode(encoding = 'ascii') print("Message {:d}:".format(i)) print("ttopic: '{}'".format(topic)) packet_size = len(data_buffer) // struct.calcsize("h") print("tpacket size: {:d}".format(packet_size)) struct_format = "{:d}h".format(packet_size) data = struct.unpack(struct_format, data_buffer) print("tdata: {}".format(data)) i += 1 except KeyboardInterrupt: socket.close() except Exception as error: print("ERROR: {}".format(error)) socket.close()
推荐阅读
- 6个顶级可视化Python库
- 你平时是怎么管理 Docker 容器的?还在使用一大堆的窗口和命令吗
- |还在流通使用的5角纸币,单张价值22000元,你有吗?
- 龙利鱼|夏季能不能使用面霜?只要用对,效果就会翻倍
- 使用 PowerDNS 轻松配置 DNS 名称服务器
- 如何消息队列的数据积压问题
- 什么是Java可变参数列表?怎么和重载机制配合使用?
- 小米|小米Civi 1S用上骁龙778G Plus!美女产品经理:日常使用非常省心
- 喝茶黑色时段,宋代饮茶为什么流行使用黑色的建盏
- 第一颗使用望远镜发现的行星 一艘飞船飞向黑洞,远方观测者
