<think>我们正在查找关于使用C++和ZeroMQ进行通信的实例。根据提供的引用,我们可以总结出几个关键点:
1. ZeroMQ支持多种通信模型,包括Request/Response、Publish/Subscribe、Push/Pull等(引用[1][2])。
2. 引用[3]提供了一个使用PUSH/PULL模式进行并行计算的例子。
3. 引用[4]介绍了独占模式(Exclusive Pair Pattern)的使用。
4. 引用[5]展示了如何配置优化订阅-发布模型,包括设置I/O线程数量等。
由于用户要求实例,我们可以提供几种常见的通信模型的简单示例代码。
### 示例1: Request/Reply模型
这是最简单的请求-响应模式。一个服务器绑定一个端口等待请求,客户端连接并发送请求,然后服务器回复。
**服务器端 (server.cpp)**:
```cpp
#include <zmq.hpp>
#include <string>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REP);
socket.bind("tcp://*:5555");
while (true) {
zmq::message_t request;
socket.recv(request, zmq::recv_flags::none); // 等待接收请求
std::cout << "Received: " << request.to_string() << std::endl;
// 模拟处理
std::string reply_msg = "World";
zmq::message_t reply(reply_msg.size());
memcpy(reply.data(), reply_msg.data(), reply_msg.size());
socket.send(reply, zmq::send_flags::none);
}
return 0;
}
```
**客户端 (client.cpp)**:
```cpp
#include <zmq.hpp>
#include <string>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);
socket.connect("tcp://localhost:5555");
// 发送请求
std::string msg = "Hello";
zmq::message_t request(msg.size());
memcpy(request.data(), msg.data(), msg.size());
socket.send(request, zmq::send_flags::none);
// 等待回复
zmq::message_t reply;
socket.recv(reply, zmq::recv_flags::none);
std::cout << "Received: " << reply.to_string() << std::endl;
return 0;
}
```
### 示例2: Publish/Subscribe模型
发布者发送消息,订阅者接收消息。注意:订阅者需要设置订阅主题(默认为接收所有消息)。
**发布者 (publisher.cpp)**:
```cpp
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <unistd.h>
int main() {
zmq::context_t context(1);
zmq::socket_t publisher(context, ZMQ_PUB);
publisher.bind("tcp://*:5556");
while (true) {
std::string msg = "Hello World";
zmq::message_t message(msg.size());
memcpy(message.data(), msg.data(), msg.size());
publisher.send(message, zmq::send_flags::none);
std::cout << "Published: " << msg << std::endl;
sleep(1);
}
return 0;
}
```
**订阅者 (subscriber.cpp)**:
```cpp
#include <zmq.hpp>
#include <string>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t subscriber(context, ZMQ_SUB);
subscriber.connect("tcp://localhost:5556");
subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0); // 订阅所有消息
while (true) {
zmq::message_t message;
subscriber.recv(message, zmq::recv_flags::none);
std::cout << "Received: " << message.to_string() << std::endl;
}
return 0;
}
```
### 示例3: Push/Pull模型(并行任务分发)
Push套接字将任务分发给多个Pull套接字(工作者),然后另一个Push/Pull用于收集结果。
**任务分发器 (ventilator.cpp)**:
```cpp
#include <zmq.hpp>
#include <vector>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t sender(context, ZMQ_PUSH);
sender.bind("tcp://*:5557");
std::cout << "Press Enter when workers are ready: ";
getchar();
std::cout << "Sending tasks to workers...\n";
// 发送任务(这里用整数模拟)
for (int task = 0; task < 100; task++) {
zmq::message_t msg(sizeof(int));
memcpy(msg.data(), &task, sizeof(int));
sender.send(msg, zmq::send_flags::none);
}
return 0;
}
```
**工作者 (worker.cpp)**:
```cpp
#include <zmq.hpp>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t receiver(context, ZMQ_PULL);
receiver.connect("tcp://localhost:5557");
zmq::socket_t sender(context, ZMQ_PUSH);
sender.connect("tcp://localhost:5558");
while (true) {
zmq::message_t task;
receiver.recv(task, zmq::recv_flags::none);
int task_num = *static_cast<int*>(task.data());
// 处理任务(这里简单模拟)
std::cout << "Processing task: " << task_num << std::endl;
// 发送结果(这里将结果设为task_num*2)
int result = task_num * 2;
zmq::message_t res_msg(sizeof(int));
memcpy(res_msg.data(), &result, sizeof(int));
sender.send(res_msg, zmq::send_flags::none);
}
return 0;
}
```
**结果收集器 (sink.cpp)**:
```cpp
#include <zmq.hpp>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t receiver(context, ZMQ_PULL);
receiver.bind("tcp://*:5558");
int total = 100;
int sum = 0;
for (int i = 0; i < total; i++) {
zmq::message_t result;
receiver.recv(result, zmq::recv_flags::none);
int res_num = *static_cast<int*>(result.data());
sum += res_num;
std::cout << "Received result: " << res_num << std::endl;
}
std::cout << "Total sum: " << sum << std::endl;
return 0;
}
```
### 注意事项
1. 在运行示例代码前,请确保已正确安装ZeroMQ库并配置了C++环境(如引用[1]提到的下载库文件)。
2. 在Windows上,使用VS2013等IDE时,需要将ZeroMQ的库文件和头文件包含到项目中。
3. 上述代码仅为简单示例,实际应用中需要处理错误和异常。
这些示例覆盖了ZeroMQ的三种主要通信模型,用户可以根据需要选择适合的模式进行开发。
§§相关问题§§
1. ZeroMQ的PUSH/PULL模式和PUB/SUB模式有什么区别?
2. 如何在Windows上配置ZeroMQ的C++开发环境?
3. ZeroMQ的独占模式(Exclusive Pair Pattern)如何实现?
</think>### C++ ZeroMQ通信实例
根据引用内容,以下是使用C++和ZeroMQ的三种典型通信实例:
#### 1. **请求-响应模式 (Request-Reply)**
```cpp
// 服务器端
#include <zmq.hpp>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REP);
socket.bind("tcp://*:5555");
while (true) {
zmq::message_t request;
socket.recv(request, zmq::recv_flags::none);
std::string msg = request.to_string();
std::cout << "Received: " << msg << std::endl;
// 发送响应
zmq::message_t reply("World", 5);
socket.send(reply, zmq::send_flags::none);
}
return 0;
}
// 客户端
#include <zmq.hpp>
int main() {
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);
socket.connect("tcp://localhost:5555");
zmq::message_t request("Hello", 5);
socket.send(request, zmq::send_flags::none);
zmq::message_t reply;
socket.recv(reply, zmq::recv_flags::none);
return 0;
}
```
特点:经典客户端/服务器模型,适用于RPC通信[^1]。
---
#### 2. **发布-订阅模式 (Publish-Subscribe)**
```cpp
// 发布者
#include <zmq.hpp>
#include <unistd.h>
int main() {
zmq::context_t context(1);
zmq::socket_t publisher(context, ZMQ_PUB);
publisher.bind("tcp://*:5556");
while (true) {
zmq::message_t message("Data update", 11);
publisher.send(message, zmq::send_flags::none);
sleep(1); // 每秒发布一次
}
return 0;
}
// 订阅者
#include <zmq.hpp>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t subscriber(context, ZMQ_SUB);
subscriber.connect("tcp://localhost:5556");
subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0); // 订阅所有消息
while (true) {
zmq::message_t update;
subscriber.recv(update, zmq::recv_flags::none);
std::cout << "Received: " << update.to_string() << std::endl;
}
return 0;
}
```
特点:一对多广播,适用于实时数据分发[^2][^5]。
---
#### 3. **并行任务分发 (Push-Pull)**
```cpp
// 任务分发器
#include <zmq.hpp>
#include <vector>
int main() {
zmq::context_t context(4); // 使用4个I/O线程优化
zmq::socket_t ventilator(context, ZMQ_PUSH);
ventilator.bind("tcp://*:5557");
std::vector<int> tasks = {1, 2, 3, 4, 5};
for (int task : tasks) {
zmq::message_t msg(sizeof(int));
memcpy(msg.data(), &task, sizeof(int));
ventilator.send(msg, zmq::send_flags::dontwait); // 异步发送
}
return 0;
}
// 工作节点
#include <zmq.hpp>
#include <iostream>
int main() {
zmq::context_t context(1);
zmq::socket_t worker(context, ZMQ_PULL);
worker.connect("tcp://localhost:5557");
while (true) {
zmq::message_t task;
worker.recv(task, zmq::recv_flags::none);
int task_id = *static_cast<int*>(task.data());
std::cout << "Processing task: " << task_id << std::endl;
}
return 0;
}
```
特点:并行流水线处理,适用于分布式计算[^3][^5]。
---
### 关键配置项
1. **I/O线程优化**(引用[5]):
```cpp
zmq::context_t context(4); // 使用4个I/O线程
```
2. **独占模式**(引用[4]):
```cpp
zmq::socket_t pair_socket(context, ZMQ_PAIR); // 独占通信
```
3. **异步发送**(引用[5]):
```cpp
socket.send(msg, zmq::send_flags::dontwait);
```
> **注意**:编译需链接`libzmq`库,Windows需下载预编译库[^1],Linux使用`apt install libzmq3-dev`。