对于内网服务器的通信采用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. zoj 1081 (改进的弧长算法)(转)

    看到网上除了射线法,很长一段代码之外,看到了一个很简单的算法解决这个问题,特意转了过来 /* 这个算法是源自<计算机图形学基础教程>(孙家广,清华大学出版社),在该书 的48-49页,名字 ...

  2. List(双向链表)

    List是一种双向链表结构,可以从第一个元素开始删除.插入,也可以从最后一个元素删除.插入,下面介绍一下 List 中常用的几个函数: 一.List 中的 begin 和 end 函数 : 和其他几种 ...

  3. poj3358 Period of an Infinite Binary Expansion 数论有难度

    这道题目感觉好难,根本就是无从下手的感觉,尝试了以前的所有方法,都没有思路,毫无进展,参考了一下别人的思路,感觉学到了新的知识 接下来开始分析 观察1/10这组数据,按照二进制转化法可以得到: 1/1 ...

  4. A Byte of Python 笔记(2)基本概念:数、字符串、转义符、变量、标识符命名、数据类型、对象

    第4章 基本概念 字面意义上的常量 如5.1.23.9.23e-3,或者 'This is a string'."It's a string!" 字符串等 常量,不能改变它的值 数 ...

  5. 模拟美萍加密狗--Rockey2虚拟狗(四)

    目录(?)[+]       首先,抱怨一下.学校个破网,似乎把我端口封了,死活分不上IP,也许是是我MAC改的太频繁了,有盗号嫌疑…… 然后,正文开始…… 其实虚拟狗几天前就写完了,可这几天上不了网 ...

  6. RFID电子标签制造封装工艺和可靠性研究

    一.目的和意义 电子标签已经成为RFID工业的主要焦点 实现低成本.大批量.高可靠性地制造电子标签是推广RFID产品应用的关键技术之一 针对RFID标签制造中核心的封装工艺开展研究,以各向异性导 ...

  7. 在qt下获取屏幕分辨率

    1,在Windows下可以使用 GetSystemMetrics(SM_CXSCREEN);GetSystemMetrics(SM_CYSCREEN) 获取.   2,在Linux下可以使用XDisp ...

  8. PhoneGap 3.0 安装

    PhoneGap 3.0  已经出来有一段时间了.3.0 提供了使用Node.js 安装,使用命令行创建.编译.运行项目.也就是可以抛弃eclipse,完全使用命令.记事本开发phonegap 项目了 ...

  9. JAVA中List、Map、Set的区别与选用

    类层次关系如下: Collection ├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap └WeakHashM ...

  10. 双网卡绑定(suse)

    网卡绑定技术有助于保证高可用性特性并提供其它优势以提高网络性能,Linux双网卡绑定实现就是使用两块网卡虚拟成为一块网卡,这个聚合起来的设备看起来是一个单独的以太网接口设备,就是两块网卡具有相同的IP ...