【分析总结框架记录】基于ZMQ的游戏网络层基础架构

对于内网服务器的通信采用zmq来进行,对于和客户端的通信采用boost的asio来。这里先来搭建zmq的基础结构。

zmq相关的知识可以去zmq官方网站查询。

这里使用zmq的push 和pull来进行通信。

先放一张结构图:


其中PushZmq是推管道, PullZmq是拉管道:

对于Push的流程是:

zmq_init()----> zmq_socket()---->zmq_connect()---->zmq_init_size()----->zmq_init_data--->zmq_send()--->zmq_msg_close()--->zmq_close()---->zma_term()

具体见代码:

PushZmq.h

  1. #ifndef __PUSH_ZMQ_H__  
  2. #define __PUSH_ZMQ_H__  
  3.   
  4. #include <zmq.h>  
  5. #include <string.h>  
  6. #include <iostream>  
  7. #include <glog/logging.h>  
  8.   
  9. using namespace std;  
  10.   
  11. class PushZmq  
  12. {  
  13. public:  
  14.     PushZmq(const char* url, void* zmqContext = NULL);  
  15.     ~PushZmq();  
  16.   
  17.     size_t Send(const char* buffer, size_t length);  
  18. private:  
  19.     string _strUrl;  
  20.     void* _ctx;  
  21.     void* _socket;  
  22. };  
  23.   
  24. #endif  

PushZmq.cpp

  1. #include "pushZmq.h"  
  2. #include "proto/hello.pb.h"  
  3.   
  4. using namespace hello;  
  5.   
  6. int main()  
  7. {  
  8.     FLAGS_minloglevel = google::INFO;  
  9.     google::InitGoogleLogging("");  
  10.     google::SetLogDestination(google::INFO, "../");  
  11.     google::SetLogFilenameExtension("log_");  
  12.     google::LogToStderr();  
  13.   
  14.     string url = "tcp://127.0.0.1:5555";  
  15.     PushZmq* push = new PushZmq(url.c_str());  
  16.     //string sendContent = "Hello Pull.I am From Push!";  
  17.     PbMsgHello helloMsg;  
  18.     helloMsg.set_helloint(123456);  
  19.     helloMsg.set_hellostring("ni hao wang peng ");  
  20.   
  21.     int length = helloMsg.ByteSize();  
  22.     char* buffer = (char*)malloc(length);  
  23.       
  24.     helloMsg.SerializeToArray(buffer, length);  
  25.     push->Send(buffer, length);  
  26.     free(buffer);  
  27.     return 0;  
  28. }  
  29.   
  30. PushZmq::PushZmq( const char* url, void* zmqContext /*= NULL*/ )  
  31. :_strUrl(url)  
  32. ,_ctx(zmqContext)  
  33. {  
  34.     if(!_ctx)  
  35.     {  
  36.         _ctx = zmq_init(1);  
  37.     }  
  38.   
  39.     _socket = zmq_socket(_ctx, ZMQ_PUSH);  
  40.     if(!_socket)  
  41.     {  
  42.         cout << "Error int zmq_socket:" << zmq_strerror(errno) << endl;  
  43.         return;  
  44.     }  
  45.   
  46.     int rc = zmq_connect(_socket, _strUrl.c_str());  
  47.     if(rc != 0 )  
  48.     {  
  49.         cout << "error in zmq_connect:" << zmq_strerror(errno) << endl;  
  50.         return;  
  51.     }  
  52. }  
  53.   
  54. PushZmq::~PushZmq()  
  55. {  
  56.     zmq_close(_socket);  
  57.     zmq_term(_ctx);  
  58. }  
  59.   
  60. size_t PushZmq::Send( const char* buffer, size_t length )  
  61. {  
  62.     zmq_msg_t msg;  
  63.     int rc = zmq_msg_init_size(&msg, length);  
  64.     memcpy((char*)zmq_msg_data(&msg), buffer, length);  
  65.   
  66.     rc = zmq_send(_socket, &msg, ZMQ_NOBLOCK);  
  67.     if(rc < 0)  
  68.     {  
  69.         cout << "error in zmq_send:" << zmq_strerror(errno) << endl;  
  70.         zmq_msg_close(&msg);  
  71.         return -1;  
  72.     }  
  73.     zmq_msg_close(&msg);  
  74.   
  75.     LOG(INFO) << "Send Hello success: rc=" << rc;    
  76.     return rc;  
  77. }  


对于Pull的流程是:

zmq_init()--->zmq_socket()--->zmq_bind()--->zmq_poll--->zmq_msg_init()---->zmq_recv()--->zmq_msg_data()--->zmq_msg_size()-------调用具体处理函数--->zmq_close-->zmq_msg_close--->zmq_close()--->zmq_term

PullZmq.h

  1. #ifndef __PULL_ZMQ_H__  
  2. #define __PULL_ZMQ_H__  
  3.   
  4. #include <zmq.h>  
  5. #include <iostream>  
  6. #include <string.h>  
  7. #include <glog/logging.h>  
  8. #include <boost/bind.hpp>  
  9. #include <boost/function.hpp>  
  10. using namespace std;  
  11.   
  12. class PullZmq  
  13. {  
  14. public:  
  15.     typedef boost::function<bool(const char*, size_t)> TypeOnMessage;  
  16.   
  17.     PullZmq(const char* url, TypeOnMessage onPipeMessage, void* zmqContext=NULL);  
  18.     ~PullZmq();  
  19.   
  20.     void Run();  
  21. private:  
  22.     void* _ctx;  
  23.     string _strUrl;  
  24.     void* _socket;  
  25.     TypeOnMessage _onMessage;  
  26. };  
  27. #endif  

PullZmq.Cpp:

  1. #include "PullZmq.h"  
  2. #include "proto/hello.pb.h"  
  3. using namespace hello;  
  4.   
  5. bool TestOnMessage( const char* buffer, size_t length );  
  6. int main()  
  7. {  
  8.     FLAGS_minloglevel = google::INFO;  
  9.     google::InitGoogleLogging("");  
  10.     google::SetLogDestination(google::INFO, "../");  
  11.     google::SetLogFilenameExtension("log_");  
  12.     google::LogToStderr();  
  13.   
  14.     string url = "tcp://*:5555";  
  15.     PullZmq* pull = new PullZmq(url.c_str(),  
  16.         boost::bind(TestOnMessage, _1, _2));  
  17.   
  18.     pull->Run();  
  19.   
  20.     return 0;  
  21. }  
  22.   
  23. PullZmq::PullZmq( const char* url, TypeOnMessage onPipeMessage, void* zmqContext )  
  24. :_strUrl(url)  
  25. ,_onMessage(onPipeMessage)  
  26. , _ctx(zmqContext)  
  27. {  
  28.     if(!_ctx)  
  29.     {  
  30.         _ctx = zmq_init(1);  
  31.         if(!_ctx)  
  32.         {  
  33.             cout << "error in zmq_init:" << zmq_strerror(errno) << endl;  
  34.             return;  
  35.         }  
  36.     }  
  37.   
  38.     _socket = zmq_socket(_ctx, ZMQ_PULL);  
  39.     if (!_socket)  
  40.     {  
  41.         LOG(ERROR) << "Error in zmq_socket:" << zmq_strerror(errno);  
  42.         return;  
  43.     }  
  44.   
  45.     int rc = zmq_bind(_socket, url);  
  46.     if(rc != 0)  
  47.     {  
  48.         LOG(ERROR) << "error in zmq_bind:" << zmq_strerror(errno);  
  49.         return;  
  50.     }  
  51. }  
  52.   
  53. PullZmq::~PullZmq()  
  54. {  
  55.     int rc = zmq_close(_socket);  
  56.     if(rc != 0)  
  57.     {  
  58.         LOG(ERROR) << "error in zmq_close:" << zmq_strerror(errno);  
  59.     }  
  60.     rc = zmq_term(_ctx);  
  61.     if(rc !=0 )  
  62.     {  
  63.         LOG(ERROR) << "error in zmq_term:" << zmq_strerror(errno);  
  64.     }  
  65. }  
  66.   
  67. void PullZmq::Run()  
  68. {  
  69.     zmq_pollitem_t item;  
  70.     item.socket = _socket;  
  71.     item.events = ZMQ_POLLIN;  
  72.   
  73.     long pollWaitTime = 1000;  
  74.     bool bLoop = true;  
  75.   
  76.     while(bLoop)  
  77.     {  
  78.         int rc = zmq_poll(&item, 1, -1);  
  79.         if(rc < 0)  
  80.         {  
  81.             LOG(ERROR) << "error in zmq_poll:" << zmq_strerror(errno);  
  82.         }else if(rc ==0)  
  83.         {  
  84.             //LOG(ERROR) << "On Idle!";  
  85.         }else   
  86.         {  
  87.             int msgCount = rc;  
  88.             while(msgCount--)  
  89.             {  
  90.                 zmq_msg_t msg;  
  91.                 rc = zmq_msg_init(&msg);  
  92.                 if (rc !=0 )  
  93.                 {  
  94.                     LOG(ERROR) << "error in zmq_msg_init:" << zmq_strerror(errno);  
  95.                     return;  
  96.                 }  
  97.   
  98.                 rc = zmq_recv(_socket, &msg, 0);  
  99.                 if(rc != 0)  
  100.                 {  
  101.                     LOG(ERROR) << "error in zmq_recv:" << zmq_strerror(errno);  
  102.                     zmq_msg_close(&msg);  
  103.                     continue;  
  104.                 }  
  105.   
  106.                 void* buffer = zmq_msg_data(&msg);  
  107.                 size_t len = zmq_msg_size(&msg);  
  108.                 bLoop = _onMessage((const char*)buffer, len);  
  109.                 zmq_msg_close(&msg);  
  110.             }  
  111.         }  
  112.     }  
  113.   
  114. }  
  115.   
  116. bool TestOnMessage( const char* buffer, size_t length )  
  117. {  
  118.     LOG(INFO) << "TestOnMessage:";  
  119.       
  120.     PbMsgHello helloMsg;  
  121.     helloMsg.ParseFromArray(buffer, length);  
  122.     LOG(INFO) << " helloInt = " << helloMsg.helloint()  
  123.         << " helloString = " << helloMsg.hellostring();  
  124.   
  125.     //string content;  
  126.     //content.append(buffer);  
  127.     //LOG(INFO) << "buffer = " << content << " length = " << length;  
  128.   
  129.     return true;  
  130. }  

对应Makefile为:

  1. all:    pull push  
  2.   
  3. hello.o:  
  4.     g++ -c -o hello.o proto/hello.pb.cc   
  5.   
  6. pull:   hello.o  
  7.     g++ -o pullZmq hello.o PullZmq.cpp -lzmq -lglog -lboost_filesystem -lprotobuf  
  8.   
  9. push:   hello.o  
  10.     g++ -o pushZmq hello.o PushZmq.cpp -lzmq -lglog -lboost_filesystem -lprotobuf  
  11.   
  12.   
  13. clean:  
  14.     rm -rf *.o  
  15.     rm -rf pullZmq  
  16.     rm -rf pushZmq  

对于上文的cpp中,开启了Protobuffer的 因此需要导入protobuffer的支持,对应proto文件

hello.proto为:

  1. package hello;  
  2. message PbMsgHello  
  3. {  
  4.     required string helloString = 1;  
  5.     required int32 helloInt =2;  
  6. }  


运行以上cpp  可以实现 在push端包装一个Protobuffer的Message 在序列化之后Push到Pull端, Pull端接受到消息后进行解析 并读Message中的内容。

结果如下:

pull端:


Push端:



可见在Push端组装的 int 和string 在pull端成功解析。


下一步应该进行Message的包装,以及ProtoBuffer的反射解析。即根据类型来自动生成解析所需的Message类型。


1-6章节对于源码下载:http://download.csdn.net/detail/jcracker/6267125

基于stm32f4的zmq1烟雾传感器代码实现需要以下步骤: 1. 首先,需要配置stm32f4的引脚,将烟雾传感器与stm32f4进行连接。根据传感器的规格书或者数据手册,了解传感器的工作原理,确定传感器的输出引脚和stm32f4的输入引脚之间的连接方式。 2. 接着,需要在stm32f4上编写代码,初始化GPIO引脚,配置输入模式,并使能所使用的GPIO外设时钟。通过GPIO的外部中断功能,可以实现当烟雾传感器检测到烟雾时,产生一个外部中断信号。 3. 在中断服务程序(ISR)中,读取传感器的输出引脚状态,判断是否检测到烟雾。如果检测到烟雾,则可以发送一个消息给ZMQ服务器,通知烟雾检测的结果。 4. 接下来,需要在stm32f4上安装ZMQ库,并编写相关代码,以实现与ZMQ服务器的通信。可以使用ZMQ的REQ-REP模式进行通信,其中STM32作为REQ端,向服务器发送烟雾检测结果的消息。 5. 在代码中,需要设置ZMQ服务器的地址和端口号,以及连接的超时时间和重试次数等参数。通过创建ZMQ的Context和Socket对象,可以建立与服务器的连接,并发送烟雾检测结果的消息。 6. 最后,通过循环等待服务器的回复消息,可以实现双向通信。可以根据服务器的回复消息,进行相应的处理或者显示。 以上就是基于stm32f4的zmq1烟雾传感器代码实现的基本步骤。具体的实现方式和代码细节,可能会根据具体的传感器型号、ZMQ库版本和应用场景等因素而有所不同。可以参考相关的资料和示例代码,进一步开发和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值