对于内网服务器的通信采用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

#ifndef __PUSH_ZMQ_H__
#define __PUSH_ZMQ_H__ #include <zmq.h>
#include <string.h>
#include <iostream>
#include <glog/logging.h> using namespace std; class PushZmq
{
public:
PushZmq(const char* url, void* zmqContext = NULL);
~PushZmq(); size_t Send(const char* buffer, size_t length);
private:
string _strUrl;
void* _ctx;
void* _socket;
}; #endif

PushZmq.cpp

#include "pushZmq.h"
#include "proto/hello.pb.h" using namespace hello; int main()
{
FLAGS_minloglevel = google::INFO;
google::InitGoogleLogging("");
google::SetLogDestination(google::INFO, "../");
google::SetLogFilenameExtension("log_");
google::LogToStderr(); string url = "tcp://127.0.0.1:5555";
PushZmq* push = new PushZmq(url.c_str());
//string sendContent = "Hello Pull.I am From Push!";
PbMsgHello helloMsg;
helloMsg.set_helloint(123456);
helloMsg.set_hellostring("ni hao wang peng "); int length = helloMsg.ByteSize();
char* buffer = (char*)malloc(length); helloMsg.SerializeToArray(buffer, length);
push->Send(buffer, length);
free(buffer);
return 0;
} PushZmq::PushZmq( const char* url, void* zmqContext /*= NULL*/ )
:_strUrl(url)
,_ctx(zmqContext)
{
if(!_ctx)
{
_ctx = zmq_init(1);
} _socket = zmq_socket(_ctx, ZMQ_PUSH);
if(!_socket)
{
cout << "Error int zmq_socket:" << zmq_strerror(errno) << endl;
return;
} int rc = zmq_connect(_socket, _strUrl.c_str());
if(rc != 0 )
{
cout << "error in zmq_connect:" << zmq_strerror(errno) << endl;
return;
}
} PushZmq::~PushZmq()
{
zmq_close(_socket);
zmq_term(_ctx);
} size_t PushZmq::Send( const char* buffer, size_t length )
{
zmq_msg_t msg;
int rc = zmq_msg_init_size(&msg, length);
memcpy((char*)zmq_msg_data(&msg), buffer, length); rc = zmq_send(_socket, &msg, ZMQ_NOBLOCK);
if(rc < 0)
{
cout << "error in zmq_send:" << zmq_strerror(errno) << endl;
zmq_msg_close(&msg);
return -1;
}
zmq_msg_close(&msg); LOG(INFO) << "Send Hello success: rc=" << rc;
return rc;
}

对于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

#ifndef __PULL_ZMQ_H__
#define __PULL_ZMQ_H__ #include <zmq.h>
#include <iostream>
#include <string.h>
#include <glog/logging.h>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std; class PullZmq
{
public:
typedef boost::function<bool(const char*, size_t)> TypeOnMessage; PullZmq(const char* url, TypeOnMessage onPipeMessage, void* zmqContext=NULL);
~PullZmq(); void Run();
private:
void* _ctx;
string _strUrl;
void* _socket;
TypeOnMessage _onMessage;
};
#endif

PullZmq.Cpp:

#include "PullZmq.h"
#include "proto/hello.pb.h"
using namespace hello; bool TestOnMessage( const char* buffer, size_t length );
int main()
{
FLAGS_minloglevel = google::INFO;
google::InitGoogleLogging("");
google::SetLogDestination(google::INFO, "../");
google::SetLogFilenameExtension("log_");
google::LogToStderr(); string url = "tcp://*:5555";
PullZmq* pull = new PullZmq(url.c_str(),
boost::bind(TestOnMessage, _1, _2)); pull->Run(); return 0;
} PullZmq::PullZmq( const char* url, TypeOnMessage onPipeMessage, void* zmqContext )
:_strUrl(url)
,_onMessage(onPipeMessage)
, _ctx(zmqContext)
{
if(!_ctx)
{
_ctx = zmq_init(1);
if(!_ctx)
{
cout << "error in zmq_init:" << zmq_strerror(errno) << endl;
return;
}
} _socket = zmq_socket(_ctx, ZMQ_PULL);
if (!_socket)
{
LOG(ERROR) << "Error in zmq_socket:" << zmq_strerror(errno);
return;
} int rc = zmq_bind(_socket, url);
if(rc != 0)
{
LOG(ERROR) << "error in zmq_bind:" << zmq_strerror(errno);
return;
}
} PullZmq::~PullZmq()
{
int rc = zmq_close(_socket);
if(rc != 0)
{
LOG(ERROR) << "error in zmq_close:" << zmq_strerror(errno);
}
rc = zmq_term(_ctx);
if(rc !=0 )
{
LOG(ERROR) << "error in zmq_term:" << zmq_strerror(errno);
}
} void PullZmq::Run()
{
zmq_pollitem_t item;
item.socket = _socket;
item.events = ZMQ_POLLIN; long pollWaitTime = 1000;
bool bLoop = true; while(bLoop)
{
int rc = zmq_poll(&item, 1, -1);
if(rc < 0)
{
LOG(ERROR) << "error in zmq_poll:" << zmq_strerror(errno);
}else if(rc ==0)
{
//LOG(ERROR) << "On Idle!";
}else
{
int msgCount = rc;
while(msgCount--)
{
zmq_msg_t msg;
rc = zmq_msg_init(&msg);
if (rc !=0 )
{
LOG(ERROR) << "error in zmq_msg_init:" << zmq_strerror(errno);
return;
} rc = zmq_recv(_socket, &msg, 0);
if(rc != 0)
{
LOG(ERROR) << "error in zmq_recv:" << zmq_strerror(errno);
zmq_msg_close(&msg);
continue;
} void* buffer = zmq_msg_data(&msg);
size_t len = zmq_msg_size(&msg);
bLoop = _onMessage((const char*)buffer, len);
zmq_msg_close(&msg);
}
}
} } bool TestOnMessage( const char* buffer, size_t length )
{
LOG(INFO) << "TestOnMessage:"; PbMsgHello helloMsg;
helloMsg.ParseFromArray(buffer, length);
LOG(INFO) << " helloInt = " << helloMsg.helloint()
<< " helloString = " << helloMsg.hellostring(); //string content;
//content.append(buffer);
//LOG(INFO) << "buffer = " << content << " length = " << length; return true;
}

对应Makefile为:

all:	pull push

hello.o:
g++ -c -o hello.o proto/hello.pb.cc pull: hello.o
g++ -o pullZmq hello.o PullZmq.cpp -lzmq -lglog -lboost_filesystem -lprotobuf push: hello.o
g++ -o pushZmq hello.o PushZmq.cpp -lzmq -lglog -lboost_filesystem -lprotobuf clean:
rm -rf *.o
rm -rf pullZmq
rm -rf pushZmq

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

hello.proto为:

package hello;
message PbMsgHello
{
required string helloString = 1;
required int32 helloInt =2;
}

运行以上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

6.基于ZMQ的游戏网络层基础架构的更多相关文章

  1. 深入浅出node.js游戏服务器开发1——基础架构与框架介绍

    2013年04月19日 14:09:37 MJiao 阅读数:4614   深入浅出node.js游戏服务器开发1——基础架构与框架介绍   游戏服务器概述 没开发过游戏的人会觉得游戏服务器是很神秘的 ...

  2. 面向服务体系架构(SOA)和数据仓库(DW)的思考基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台

    面向服务体系架构(SOA)和数据仓库(DW)的思考 基于 IBM 产品体系搭建基于 SOA 和 DW 的企业基础架构平台 当前业界对面向服务体系架构(SOA)和数据仓库(Data Warehouse, ...

  3. 基于SpringBoot搭建应用开发框架(一) —— 基础架构

    目录 Spring的简史 零.开发技术简介 一.创建项目 1.创建工程 2.创建Starter 3.启动项目 4.Spring Boot 配置 5.项目结构划分 二.基础结构功能 1.web支持 2. ...

  4. 基于cocos2d-x的游戏框架设计——李成

    视频:http://v.youku.com/v_show/id_XMzc5ODUyMTI4.html?f=17330006 网易科技讯 3月31日,第四届CocoaChina开发者大会暨Cocos2d ...

  5. 《Unity 3D游戏客户端基础框架》概述

    框架概述: 做了那么久的业务开发,也做了一年多的核心战斗开发,最近想着自己倒腾一套游戏框架,当然暂不涉及核心玩法类型和战斗框架,核心战斗的设计要根据具体的游戏类型而定制,这里只是一些通用的基础系统的框 ...

  6. QQ和微信凶猛成长的背后:腾讯网络基础架构的这些年

    本文来自腾讯资深架构师杨志华的分享. 1.前言 也许没有多少人记得2004年发生的事情.但对于老腾讯来说,14年前的那个日子,2004年6月16日永远难以忘怀.这一天,QQ诞生5年后的腾讯在香港联交所 ...

  7. 基于Lua的游戏服务端框架简介

    基于Lua的游戏服务端框架简介 [转]https://gameinstitute.qq.com/community/detail/106396 基于lua的游戏服务端框架简介 1. 引言 笔者目前在参 ...

  8. IT基础架构规划方案一(网络系统规划)

    背景                   某集团经过多年的经营,公司业务和规模在不断发展,公司管理层和IT部门也认识到通过信息化手段可以更好地支撑公司业务运营.提高企业生产和管理效率.同时随着新建办公 ...

  9. b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释

    继续上篇,上篇里忘记了也很重要的前端部分,今天的网站基本上是以一个启示页,然后少量的整页切换,大量的浏览器后台调用web服务局部.动态更新页面显示状态这种方式在运作的,从若干年前简单的ajax流行起来 ...

随机推荐

  1. 获取当前WEB应用全路径

    <%String path = request.getContextPath();String basePath =request.getScheme()+"://"+req ...

  2. php内核--SAPI概述

  3. python初探-copy

    python中,数据的拷贝有以下三种形式:赋值.浅copy和深copy.根据类型的不同,可以把数据分成以下两类:字符串和数字为一类,其他(包括列表.元祖.字典...)为一类. 在python中有池的概 ...

  4. Loadrunner11点击录制脚本无响应,IE页面弹不出——解决方案汇总

    以前用Loadrunner的时候都没有遇到过这个问题,后来将服务器重装系统(win7)后,重新安装Loadrunner11,浏览器版本刚开始为IE11,后来降为IE8,IE访问部署在虚拟机里的平台能正 ...

  5. 数据库导出到excel

    项目结构同上一篇 泛型通用的写法 ExportExcel.java package excel; import java.io.OutputStream; import java.lang.refle ...

  6. 在OSX狮子(Lion)上安装MYSQL(Install MySQL on Mac OSX)

    这篇文章简述了在Mac OSX狮子(Lion)上安装MySQL Community Server最新版本v10.6.7的过程. MySQL是最流行的开源数据库管理系统.首先,从MySQL的下载页面上下 ...

  7. 宣布正式发布 Windows Azure 上的 Oracle 软件以及 Windows Azure Traffic Manager 更新

     Windows Azure 的核心原则之一就是为客户提供一个开放.灵活的平台.今天是一个令人振奋的里程碑,因为我们与 Oracle 的合作又向前迈进了一步.Oracle Database.Ora ...

  8. cocos2d-x删除vs2010项目模板

    假设你切换cocos2d-x版本号的话. 要将之前版本号的vs模板删除掉.方法例如以下: 进入下面文件夹(依据自己的vs版本号): VS2008: C:\Program Files\Microsoft ...

  9. VS快捷键简单记录

    代码上下移动行:Alt+上下键 跳转相等大括号:Ctrl+]

  10. VPN连接在遇到飞鱼星设备时可能出现的疑难问题

    在连接VPN设备时,设置都是正常的.在