zmq poll实例

本文介绍了一个使用ZeroMQ库实现的多通道通信示例,包括一个服务器端和两个客户端之间的非阻塞通信实现。该示例展示了如何通过ZMQ_PULL和ZMQ_PUSH套接字类型,在两个不同的端口上进行消息的发送与接收。

注意:此时不可以用ZMQ_REP ZMQ_REQ。  因为ZMQ_REQ发送一次数据后,如果没有收到数据,不能再次发送数据。 

 

ZmqIOServer端:

[cpp]  view plain copy
  1. #include <assert.h>  
  2. #include <iostream>  
  3. #include <tchar.h>  
  4. #include <zmq.h>  
  5. using namespace std;  
  6.   
  7. #pragma comment(lib,"libzmq.lib")  
  8.   
  9. void main(int argc,TCHAR*argv[])  
  10. {  
  11.     void *ctx;  
  12.     ctx = zmq_init(1);  
  13.     assert(ctx);  
  14.   
  15.     void *s1;  
  16.     s1 = zmq_socket(ctx,ZMQ_PULL);  
  17.     assert(s1);  
  18.   
  19.     void *s2;  
  20.     s2 = zmq_socket(ctx,ZMQ_PULL);  
  21.     assert(s2);  
  22.   
  23.     zmq_bind(s1,"tcp://127.0.0.1:6000");  
  24.     zmq_bind(s2,"tcp://127.0.0.1:7000");  
  25.   
  26.     while(1)  
  27.     {  
  28.         zmq_pollitem_t items[2];  
  29.         items[0].socket = s1;  
  30.         items[0].fd = 0;  
  31.         items[0].events = ZMQ_POLLIN;  
  32.   
  33.         items[1].socket = s2;  
  34.         items[1].fd = 0;  
  35.         items[1].events = ZMQ_POLLIN;  
  36.         int nRet = zmq_poll(items,2,-1);  
  37.         if(0 == nRet)  
  38.             continue;  
  39.   
  40.         zmq_msg_t msg;  
  41.         char re_string[20] = {0};  
  42.   
  43.         if(items[0].revents > 0)  
  44.         {  
  45.             zmq_msg_init(&msg);  
  46.             zmq_recv(s1,&msg,0);  
  47.             memcpy(re_string,(char*)zmq_msg_data(&msg),zmq_msg_size(&msg));  
  48.             cout<<"Socket1 recv : "<<re_string<<endl;  
  49.             zmq_msg_close(&msg);  
  50.         }  
  51.   
  52.         if(items[1].revents > 0)  
  53.         {  
  54.             zmq_msg_init(&msg);  
  55.             zmq_recv(s2,&msg,0);  
  56.             memcpy(re_string,(char*)zmq_msg_data(&msg),zmq_msg_size(&msg));  
  57.             cout<<"Socket2 recv : "<<re_string<<endl;  
  58.             zmq_msg_close(&msg);  
  59.         }  
  60.     }  
  61.       
  62.     zmq_close(s1);  
  63.     zmq_close(s2);  
  64.     zmq_term(ctx);  
  65. }  


ZmqIOClient1端:

[cpp]  view plain copy
  1. #include <assert.h>  
  2. #include <iostream>  
  3. #include <tchar.h>  
  4. #include <zmq.h>  
  5. using namespace std;  
  6.   
  7. #pragma comment(lib,"libzmq.lib")  
  8.   
  9. void main(int argc,TCHAR*argv[])  
  10. {  
  11.     void *ctx;  
  12.     ctx = zmq_init(1);  
  13.     assert(ctx);  
  14.   
  15.     void *s1;  
  16.     s1 = zmq_socket(ctx,ZMQ_PUSH);  
  17.     assert(s1);  
  18.   
  19.     zmq_connect(s1,"tcp://127.0.0.1:6000");  
  20.   
  21.     while(1)  
  22.     {  
  23.         char sd_string[20];  
  24.         cout<<"请输入sd_string:"<<endl;  
  25.         gets(sd_string);  
  26.   
  27.         zmq_msg_t msg;zmq_msg_init_size(&msg,strlen(sd_string)+1);  
  28.         memcpy(zmq_msg_data(&msg),sd_string,strlen(sd_string)+1);  
  29.         zmq_send(s1,&msg,0);  
  30.         zmq_msg_close(&msg);  
  31.     }  
  32.   
  33.     zmq_close(s1);  
  34.     zmq_term(ctx);  
  35. }  


ZmqIOClient2端:

[cpp]  view plain copy
  1. #include <assert.h>  
  2. #include <iostream>  
  3. #include <tchar.h>  
  4. #include <zmq.h>  
  5. using namespace std;  
  6.   
  7. #pragma comment(lib,"libzmq.lib")  
  8.   
  9. void main(int argc,TCHAR*argv[])  
  10. {  
  11.     void *ctx;  
  12.     ctx = zmq_init(1);  
  13.     assert(ctx);  
  14.   
  15.     void *s1;  
  16.     s1 = zmq_socket(ctx,ZMQ_PUSH);  
  17.     assert(s1);  
  18.   
  19.     zmq_connect(s1,"tcp://127.0.0.1:7000");  
  20.   
  21.     while(1)  
  22.     {  
  23.         char sd_string[20];  
  24.         cout<<"请输入sd_string2:"<<endl;  
  25.         gets(sd_string);  
  26.   
  27.         zmq_msg_t msg;  
  28.         zmq_msg_init_size(&msg,strlen(sd_string)+1);  
  29.         memcpy(zmq_msg_data(&msg),sd_string,strlen(sd_string)+1);  
  30.         zmq_send(s1,&msg,0);  
  31.         zmq_msg_close(&msg);  
  32.     }  
  33.   
  34.     zmq_close(s1);  
  35.     zmq_term(ctx);  
  36. }  
<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`。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值