ZeroMQ的ZMQ_STREAM模式写的服务器反向先发请求的示例代码
来源:互联网 发布:pkpm网络计划软件 编辑:程序博客网 时间:2024/05/21 08:00
bool has_more(void* socket){int more = 0;size_t more_size = sizeof(more);int rc = zmq_getsockopt(socket, ZMQ_RCVMORE, &more, &more_size);if (rc != 0)return false;return more != 0;}#include <string>#include <map>#include <vector>#include <set>bool bExitClient = false;bool bExitServer = false;//ZmqStreamServerProc - 服务端线程函数DWORD WINAPI ZmqStreamServerProc(LPVOID lpThreadParameter) {int rc;std::set<std::string> peer_ids;DWORD prev_tick = GetTickCount();//创建contextvoid *ctx = zmq_ctx_new();assert(ctx);//创建socket并设置属性void *server = zmq_socket(ctx, ZMQ_STREAM);assert(server);int enabled = 1;rc = zmq_setsockopt(server, ZMQ_STREAM_NOTIFY, &enabled, sizeof(enabled));assert(rc == 0);//绑定端口rc = zmq_bind(server, "tcp://127.0.0.1:9070");assert(rc == 0);while (!bExitServer) {//对socket进行poll操作zmq_pollitem_t items[] = {{ server, 0, ZMQ_POLLIN, 0 },};rc = zmq_poll(items, 1, 100);if (rc == 1) {if (items[0].revents & ZMQ_POLLIN) {//有数据可读,分为两种情况,一种是STREAM NOTIFY,一种是真实的客户端发出的数据zmq_msg_t peer_frame;//接收1st 对端ID帧rc = zmq_msg_init(&peer_frame);assert(rc == 0);rc = zmq_msg_recv(&peer_frame, server, 0);assert(rc != -1);assert(zmq_msg_size(&peer_frame) > 0);assert(has_more(server));char * p_peer_frame_data = (char*)zmq_msg_data(&peer_frame);//TRACE("peer_id:%s\n", p_peer_frame_data);std::string str_peer_id(p_peer_frame_data, zmq_msg_size(&peer_frame));zmq_msg_close(&peer_frame);//接收2nd 对端数据帧zmq_msg_t data_frame;rc = zmq_msg_init(&data_frame);assert(rc == 0);rc = zmq_msg_recv(&data_frame, server, 0);assert(rc != -1);if (zmq_msg_size(&data_frame) == 0) {if (peer_ids.find(str_peer_id) == peer_ids.end()) {TRACE("S :a new conn incoming\n");peer_ids.insert(str_peer_id);}else {TRACE("S :an exsit conn disconnected\n");peer_ids.erase(str_peer_id);}}else {char * p_data_frame_data = (char*)zmq_msg_data(&data_frame);TRACE("S :recv [%s]\n", p_data_frame_data);}zmq_msg_close(&data_frame);}/*if (items[0].revents & ZMQ_POLLERR) {TRACE("S :ZMQ_POLLERR\n");}*/}else if (rc == 0) {//0 表示poll没有相应事件,可认为socket出于空闲状态。//TRACE("S :zmq_poll() return 0\n");//assert(false);//模拟每3秒钟给所有客户端发出请求if (peer_ids.size() > 0 && (GetTickCount() - prev_tick) > 3000) {for (auto iter = peer_ids.begin(); iter != peer_ids.end(); ++iter) {//服务器端先发出请求//发出1st ID帧rc = zmq_send(server, iter->c_str(), iter->size(), ZMQ_SNDMORE);//TRACE("S :send identity res=%d errno=%d\n", rc, errno);//assert(rc != -1);//发出2nd 数据帧TRACE("S :send:[%s]\n", "hello");rc = zmq_send(server, "hello", 6, ZMQ_SNDMORE);//assert(rc != -1);}prev_tick = GetTickCount();}}else {TRACE("S :zmq_poll() return error\n");assert(false);}}rc = zmq_close(server);assert(rc == 0);rc = zmq_ctx_term(ctx);assert(rc == 0);return 0;}//ZmqStreamClientProc - 客户端线程函数DWORD WINAPI ZmqStreamClientProc(LPVOID lpThreadParameter) {int rc;// Set-up our context and socketsvoid *ctx = zmq_ctx_new();assert(ctx);int enabled = 1;void *client = zmq_socket(ctx, ZMQ_STREAM);assert(client);rc = zmq_setsockopt(client, ZMQ_STREAM_NOTIFY, &enabled, sizeof(enabled));assert(rc == 0);rc = zmq_connect(client, "tcp://localhost:9070");uint8_t id_opt[256];size_t id_size_opt;uint8_t id_c[256];size_t id_size_c = 256;uint8_t buffer[256];rc = zmq_getsockopt(client, ZMQ_IDENTITY, id_opt, &id_size_opt);assert(rc == 0);//// Client: First frame is identity, second frame is zero//id_size_c = zmq_recv(client, id_c, 256, 0);///*TRACE("id_size = zmq_recv (client, id, 256, 0) -> id_size_c=%d\r\n", id_size_c);//for (size_t i = 0; i < id_size_c; ++i) {//TRACE("0x%02x \n", id_c[i]);//}//TRACE("\r\n");*///assert(id_size_c > 0);//rc = zmq_recv(client, buffer, 256, 0);//assert(rc == 0);while (!bExitClient) {//对socket进行poll操作zmq_pollitem_t items[] = {{ client, 0, ZMQ_POLLIN, 0 },};rc = zmq_poll(items, 1, 100);if (rc == 1) {if (items[0].revents & ZMQ_POLLIN) {//有数据可读,分为两种情况,一种是STREAM NOTIFY,一种是真实的客户端发出的数据zmq_msg_t peer_frame;//接收1st 对端ID帧rc = zmq_msg_init(&peer_frame);assert(rc == 0);rc = zmq_msg_recv(&peer_frame, client, 0);assert(rc != -1);assert(zmq_msg_size(&peer_frame) > 0);assert(has_more(client));char * p_peer_frame_data = (char*)zmq_msg_data(&peer_frame);//TRACE("peer_id:%s\n", p_peer_frame_data);std::string str_peer_id(p_peer_frame_data, zmq_msg_size(&peer_frame));zmq_msg_close(&peer_frame);//接收2nd 对端数据帧zmq_msg_t data_frame;rc = zmq_msg_init(&data_frame);assert(rc == 0);rc = zmq_msg_recv(&data_frame, client, 0);assert(rc != -1);if (zmq_msg_size(&data_frame) == 0) {}else {char * p_data_frame_data = (char*)zmq_msg_data(&data_frame);TRACE("C :recv [%s]\n", p_data_frame_data);assert(memcmp(p_data_frame_data, "hello", 6) == 0);rc = zmq_send(client, str_peer_id.c_str(), str_peer_id.size(), ZMQ_SNDMORE);assert(rc != -1);TRACE("C :send:[world!]\n");rc = zmq_send(client, "world!", 7, 0);assert(rc != -1);}zmq_msg_close(&data_frame);}if (items[0].revents & ZMQ_POLLOUT) {}if (items[0].revents & ZMQ_POLLERR) {TRACE("C :ZMQ_POLLERR");}}else if (rc == 0) {//TRACE("C :zmq_poll() return 0\n");//assert(false);}else {TRACE("C :zmq_poll() return error\n");//assert(false);}}rc = zmq_close(client);assert(rc == 0);rc = zmq_ctx_term(ctx);assert(rc == 0);return 0;}void CZmqStreamCommDemoDlg::OnBnClickedButton1(){DWORD tid;bExitServer = false;HANDLE hServerThread = CreateThread(NULL, 0, ZmqStreamServerProc, NULL, 0, &tid);CloseHandle(hServerThread);}void CZmqStreamCommDemoDlg::OnBnClickedButton2(){bExitClient = false;DWORD tid;HANDLE hThread = CreateThread(NULL, 0, ZmqStreamClientProc, NULL, 0, &tid);CloseHandle(hThread);}void CZmqStreamCommDemoDlg::OnBnClickedButton3(){bExitClient = true;}void CZmqStreamCommDemoDlg::OnBnClickedButton4(){bExitServer = true;}
2016-06-08 在实际代码中测试发现接收方收到的数据虽然是以zmq_msg_t 为边界,但有可能是由发送方的多包数据组成的,所以接收方还应严格按照自定义的协议格式来分解出多个包。
0 0
- ZeroMQ的ZMQ_STREAM模式写的服务器反向先发请求的示例代码
- 【服务器架构】ZeroMQ 的模式
- ZeroMQ 的模式
- ZeroMQ 的模式
- ZeroMQ 的模式
- ZeroMQ 的模式
- zeromq的各种模式
- ZeroMQ 的模式
- ZeroMQ 的模式
- ZeroMQ 的模式
- zeromq 的 ZMQ_DEALER 模式
- ZeroMQ:订阅-发布模式的java程序示例
- 初探ZeroMQ(五) 请求-响应模式的各种可靠性设计
- ZeroMQ的第一个代码
- zeromq的几种模式
- zeromq的几种模式
- zeromq 的发布 订阅模式
- http post 请求的示例代码
- 【HNOI2015】开店(shop)
- [计算机组成原理][R-I-J型指令CPU设计实验总结]
- 4位全加器VHDL描述
- uva_10078_The Art Gallery
- 解决上一层div浮动后下一层div跳到上一层div的问题
- ZeroMQ的ZMQ_STREAM模式写的服务器反向先发请求的示例代码
- iOS XMPP框架学习
- C语言程序设计飞机游戏的体会
- java的concurrent
- 软件开发过程-代码静态审查
- fzu1894 自愿者选拔
- C#实现百度地图附近搜索&调用JavaScript函数
- HDU 1408 盐水的故事(模拟题目)
- LeetCode 10. Regular Expression Matching