1.简介
ZeroMQ (也称为 ØMQ, zmq 或 libzmq) 是一个高性能的异步消息传递库,用于构建分布式或并发应用程序。它提供了一个消息队列的抽象,允许不同的计算机和进程之间进行消息传递,而无需关心底层网络细节。ZeroMQ 不是一个传统意义上的消息队列服务器,而是一个嵌入到应用程序中的库,它提供了多种消息传递模式,如请求-应答、发布-订阅、推-拉等。
ZeroMQ不是单独的服务或者程序,仅仅是一套组件,其封装了网络通信、消息队列、线程调度等功能,向上层提供简洁的API,应用程序通过加载库文件,调用API函数来实现高性能网络通信。
ZeroMQ(0MQ)提供了多种不同的消息传递模型,每种模型都适用于不同的通信场景。以下是ZeroMQ提供的几种主要模型简介:
-
请求-应答(REQ/REP) 模式:客户端发送请求,服务器接收请求并发送应答;客户端可以是1~N个。该模型主要用于远程调用及任务分配。 应用场景:客户端-服务器通信,如RPC(远程过程调用)。
-
发布-订阅(PUB/SUB) 模式:发布者发布消息到主题,订阅者接收消息;发布端单向分发数据,且不关心是否把全部信息发送给订阅端。如果发布端开始发布信息时,订阅端尚未连接上来,则这些信息会被直接丢弃;订阅端只负责接收,而不能反馈。 应用场景:消息队列、消息广播。
-
推送-拉取(PUSH/PULL) 模式:推送者发送数据,拉取者接收数据;与发布订阅模型相比,推拉模型在没有消费者的情况下,发布的消息不会被消耗掉;该模型主要用于多任务并行处理。 应用场景:数据管道、批处理。
2.环境搭建
解压后,使用cmake进行编译。
接下来就是Configure --> Generate --> Open Project一连三键。
拷贝源码的include目录和生成的lib库到我们的demo程序中,配置好visual studio的环境。
还有一个CPP的版本库。 github.com/zeromq/zmqp…
3.常用接口介绍
-
zmq_ctx_new - 创建新的ZeroMQ上下文 函数原型:int zmq_ctx_new (void) 功能:创建一个新的ZeroMQ上下文,用于管理套接字和事件循环。 返回值:如果成功,返回上下文句柄;如果失败,返回-1。
-
zmq_ctx_term - 销毁ZeroMQ上下文 函数原型:int zmq_ctx_term (void *context) 功能:销毁指定的ZeroMQ上下文,释放所有资源。 参数:context - 上下文句柄。 返回值:如果成功,返回0;如果失败,返回-1。
-
zmq_socket - 创建套接字 函数原型:int zmq_socket (void *context, int type) 功能:创建一个新的套接字,指定其类型。 参数:context - 上下文句柄;type - 套接字类型(如ZMQ_REQ、ZMQ_REP等)。 返回值:如果成功,返回套接字句柄;如果失败,返回-1。
-
zmq_bind - 绑定套接字到地址 函数原型:int zmq_bind (void socket, const char endpoint) 功能:将套接字绑定到指定的地址。 参数:socket - 套接字句柄;endpoint - 套接字地址。 返回值:如果成功,返回0;如果失败,返回-1。
-
zmq_connect - 连接套接字到地址 函数原型:int zmq_connect (void *socket, const char *endpoint) 功能:将套接字连接到指定的地址。 参数:socket - 套接字句柄;endpoint - 套接字地址。 返回值:如果成功,返回0;如果失败,返回-1。
-
zmq_send - 发送消息 函数原型:int zmq_send (void *socket, const void *buffer,size_t size, int flags) 功能:向套接字发送消息。 参数:socket - 套接字句柄;buffer -消息缓冲区;size - 消息大小;flags - 发送选项。 返回值:如果成功,返回实际发送的字节数;如果失败,返回-1。
-
zmq_recv - 接收消息 函数原型:int zmq_recv (void *socket, void *buffer, size_t size, int flags) 功能:从套接字接收消息。 参数:socket - 套接字句柄;buffer - 消息缓冲区;size -缓冲区大小;flags - 接收选项。 返回值:如果成功,返回实际接收的字节数;如果失败,返回-1。
-
zmq_close - 关闭套接字 函数原型:int zmq_close (void *socket) 功能:关闭指定的套接字,释放所有资源。 参数:socket - 套接字句柄。 返回值:如果成功,返回0;如果失败,返回-1。
-
zmq_setsockopt - 设置套接字选项 函数原型:int zmq_setsockopt (void *socket, int option_name, const void *option_value, size_t option_len) 功能:设置套接字的选项。 参数:socket - 套接字句柄;option_name - 选项名称;option_value -选项值
4.示例
请求/应答模式
//服务端
#include <zmq.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// 创建上下文
void *context = zmq_ctx_new();
// 创建套接字
void *receiver = zmq_socket(context, ZMQ_REP);
// 绑定套接字到端口
zmq_bind(receiver, "tcp://127.0.0.1:5555");
while (1) {
// 接收消息
char buffer[10] = { 0 };
zmq_recv(receiver, buffer, 10, 0);
printf("Received request: [%s]\n", buffer);
// 发送应答
zmq_send(receiver, "World", 5, 0);
}
// 清理资源
zmq_close(receiver);
zmq_ctx_term(context);
return 0;
}
//客户端
#include <zmq.h>
#include <stdio.h>
#include <string.h>
int main()
{
// 创建上下文
void *context = zmq_ctx_new();
// 创建套接字
void *sender = zmq_socket(context, ZMQ_REQ);
// 连接套接字到服务器
zmq_connect(sender, "tcp://127.0.0.1:5555");
// 发送请求
char buffer[10] = {0};
strcpy(buffer, "Hello");
zmq_send(sender, buffer, 5, 0);
// 接收应答
zmq_recv(sender, buffer, 10, 0);
printf("Received response: [%s]\n", buffer);
// 清理资源
zmq_close(sender);
zmq_ctx_term(context);
return 0;
}
发布/订阅模式 订阅者使用 ZMQ_SUB 套接字类型,它会连接到服务器的地址,并订阅所有主题。当发布者发送消息时,订阅者会接收并打印出来。
//发布者
int main(void)
{
// 创建上下文
void *context = zmq_ctx_new();
// 创建套接字
void *publisher = zmq_socket(context, ZMQ_PUB);
// 绑定套接字到端口
zmq_bind(publisher, "tcp://*:5555");
while (1) {
// 发送消息
char buffer[10] = {0};
sprintf(buffer, "Hello");
zmq_send(publisher, buffer, strlen(buffer), 0);
printf("Sent message: [%s]\n", buffer);
}
// 清理资源
zmq_close(publisher);
zmq_ctx_term(context);
return 0;
}
//订阅者
int main()
{
// 创建上下文
void *context = zmq_ctx_new();
// 创建套接字
void *subscriber = zmq_socket(context, ZMQ_SUB);
// 连接套接字到服务器
zmq_connect(subscriber, "tcp://localhost:5555");
// 订阅一个主题
zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
while (1) {
// 接收消息
char buffer[10] = { 0 };
zmq_recv(subscriber, buffer, 10, 0);
printf("Received message: [%s]\n", buffer);
}
// 清理资源
zmq_close(subscriber);
zmq_ctx_term(context);
return 0;
}
运行截图。
推/拉模式
//PUSH
int main(void)
{
// 创建上下文
void *context = zmq_ctx_new();
// 创建套接字
void *pusher = zmq_socket(context, ZMQ_PUSH);
// 绑定套接字到端口
zmq_bind(pusher, "tcp://*:5555");
while (1) {
// 发送消息
char buffer[10] = { 0 };
sprintf(buffer, "Hello");
zmq_send(pusher, buffer, strlen(buffer), 0);
printf("Sent message: [%s]\n", buffer);
}
// 清理资源
zmq_close(pusher);
zmq_ctx_term(context);
return 0;
}
//PULL
int main(void)
{
// 创建上下文
void *context = zmq_ctx_new();
// 创建套接字
void *puller = zmq_socket(context, ZMQ_PULL);
// 连接套接字到服务器
zmq_connect(puller, "tcp://localhost:5555");
while (1) {
// 接收消息
char buffer[10] = {0};
zmq_recv(puller, buffer, 10, 0);
printf("Received message: [%s]\n", buffer);
}
// 清理资源
zmq_close(puller);
zmq_ctx_term(context);
return 0;
}