常规的网络编程,在消息处理上大概会采用如下方式
struct msg{ int msg_id; int msg_len;
//...msg_info };
定义如上的消息结构
接收方接收后,按如上的消息结构解析数据
struct msg * _msg = (struct msg*)data;
然后消息处理,会按msg_id,将消息分发到不同的消息处理函数
switch(_msg->msg_id){ case 1: //do anything break; default: break; }
RPC则是对这种繁琐的消息处理过程做了封装,自动生成一一对应的消息响应代码,使开发者可以专注于逻辑的处理。
典型的RPC框架有protobuf、thrift,这些RPC提供了作为网络消息定义的DSL语言,用户使用DSL语言定义需要的网络事件,RPC框架即可自动生成客户端的发送和服务端的响应代码,而用户只需要按框架的约束实现网络通信的部分,即可专注于逻辑代码的编写,而不需要处理繁琐而重复的消息响应代码。
juggle是abelkhan服务器框架中的RPC框架。
这个框架采用高度解耦的设计,对数据的打包部分做了分离,而专注于消息响应代码的生成。目前支持c++和c# 2种语言。
使用juggle的方式如下:
定义DSL脚本
module test{ void test_func(string argv1, int argv2); }
使用codegen生成代码:
juggle采用python3.5编写,使用前需要安装python3.5,然后进入juggle所在的目录
如需生成c++代码测执行gencpp.py脚本,如需生成c#代码测执行gencsharp.py脚本
生成的代码如下:
c++代码:
客户端:
/*this caller file is codegen by juggle for c++*/ #include <sstream> #include <tuple> #include <string> #include <Icaller.h> #include <Ichannel.h> #include <boost/any.hpp> #include <boost/make_shared.hpp> namespace caller { class test : public juggle::Icaller { public: test(boost::shared_ptr<juggle::Ichannel> _ch) : Icaller(_ch) { module_name = "test"; } ~test(){ } void test_func(std::string argv0,int64_t argv1){ auto v = boost::make_shared<std::vector<boost::any> >(); v->push_back("test"); v->push_back("test_func"); v->push_back(boost::make_shared<std::vector<boost::any> >()); (boost::any_cast<boost::shared_ptr<std::vector<boost::any> > >((*v)[2]))->push_back(argv0); (boost::any_cast<boost::shared_ptr<std::vector<boost::any> > >((*v)[2]))->push_back(argv1); ch->push(v); } }; }
服务器端
/*this module file is codegen by juggle for c++*/ #include <Imodule.h> #include <boost/shared_ptr.hpp> #include <boost/signals2.hpp> #include <string> namespace module { class test : public juggle::Imodule { public: test(){ module_name = "test"; protcolcall_set.insert(std::make_pair("test_func", boost::bind(&test::test_func, this, _1))); } ~test(){ } boost::signals2::signal<void(std::string, int64_t) > sigtest_funchandle; void test_func(boost::shared_ptr<std::vector<boost::any> > _event){ sigtest_funchandle( boost::any_cast<std::string>((*_event)[0]), boost::any_cast<int64_t>((*_event)[1])); } }; }
使用时客户端定义caller::test对象调用test_func即可,服务器端定义module::test 将响应函数连接到sigtest_funchandle即可。
juggle地址:https://github.com/qianqians/abelkhan/tree/master/juggle
欢迎大家到abelkhan的相关论坛提出bug和意见:http://abelkhan.com/forum.php?mod=forumdisplay&fid=2