ZeroMQ是无代理、高性能异步消息库,非传统消息队列服务;它以套接字抽象替代TCP/UDP细节,支持跨进程、跨机器、跨语言通信,核心在于正确选择模式、初始化上下文与套接字、严格管理生命周期。

ZeroMQ不是传统意义的“消息队列服务”,而是一个无代理(brokerless)、高性能的异步消息传递库。它用套接字抽象替代了底层TCP/UDP细节,让C++程序能以极低开销实现进程间、跨机器甚至跨语言的通信。关键不在“装队列”,而在选对模式、建好上下文、管住生命周期。
初始化上下文和套接字是第一步
每个C++ ZeroMQ程序都从一个上下文(zmq::context_t)开始,它是线程安全的,整个进程通常只需一个:
- 创建时指定工作线程数,例如
zmq::context_t context(1)表示启用1个I/O线程 - 套接字(zmq::socket_t)必须从该上下文中构造,类型决定通信行为:ZMQ_REQ(客户端)、ZMQ_REP(服务端)、ZMQ_PUB/ZMQ_SUB(发布/订阅)、ZMQ_PUSH/ZMQ_PULL(任务分发)
- 服务端调用
bind("tcp://*:5555")监听;客户端调用connect("tcp://localhost:5555")连接——注意地址格式统一用tcp,不需手动建连接
按场景选通信模式,别混用REQ和PUB
ZeroMQ有多种内建模式,选错会导致阻塞、丢消息或收不到数据:
- REQ/REP:严格同步请求-响应,一问一答,顺序不能乱。客户端发完必须recv等回包,服务端收完必须send回数据,否则卡死
-
PUB/SUB:单向广播,发布者不关心谁在听。订阅者需用
setsockopt(ZMQ_SUBSCRIBE, "topic", 5)设置过滤前缀,且只收到连接建立后的消息(之前发的全丢) - PUSH/PULL:天然负载均衡,适合分发任务。PUSH端轮询发送,PULL端自动竞争接收,无需协调
消息收发要处理二进制安全与多段结构
ZeroMQ传输的是原始字节流,不解析内容,所以支持任意序列化格式(Protobuf、JSON、自定义结构体):
立即学习“C++免费学习笔记(深入)”;
- 发送字符串:
zmq::message_t msg("hello", 5); socket.send(msg); - 发送结构体:
MyStruct data = {...}; zmq::message_t msg(&data, sizeof(data)); socket.send(msg); - 多部分消息(如header+body):前几段调用
send(msg, ZMQ_SNDMORE),最后一段不加标志;接收方用msg.more()判断是否还有下一段
资源释放不能省,否则会内存泄漏
ZeroMQ对象不是RAII全自动管理的,显式释放是硬性要求:
- 套接字用完必须
socket.close(),否则占用端口和文件描述符 - 上下文必须
context.close(),尤其在长期运行的服务中,漏掉会导致句柄耗尽 - 如果使用多线程,确保一个上下文被多个线程共享是安全的,但套接字不能跨线程共用(除非显式设置ZMQ_THREAD_SAFE)
基本上就这些。不需要部署中间件,也不依赖系统消息队列服务,编译链接libzmq和cppzmq后,几行代码就能跑通分布式节点通信。难点不在语法,而在理解每种模式的语义约束。











