+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2019-08(82)

2019-09(116)

2019-10(2)

【C++中消息自动派发之四】使用IDL构建Chat Server

发布于2019-09-06 13:21     阅读(352)     评论(0)     点赞(13)     收藏(2)


前一篇blog 讲了如何实现IDL 解析器,本篇通过IDL解析器构建一个聊天服务器程序。本程序用来测试IDL解析器的功能,网络层使用前边blog中介绍的ffown库。我们只需定义chat.idl文件,idl解析器自动生成消息排放代码,省了每次再去繁琐的编写消息解析、判断代码。

IDL解析器介绍:http://www.cnblogs.com/zhiranok/archive/2012/02/23/json_to_cpp_struct_idl_parser_second.html

ffown socket库:http://www.cnblogs.com/zhiranok/archive/2011/12/24/cpp_epoll_socket.html

1. 场景设定

1>. user 登入系统,检查是否重登陆,若登陆过则返回出错(由于无passwor认证,只好采用”抢注“方式,uid抢先登入者可登入)。user登入后须获取在线的用户ID列表。同时该user上线消息也应该推送给在线的其他用户。

2>. user 登出,从服务器中删除用户信息,关闭socket。广播给所有在线用户该用户下线。

3>. chat 聊天。用户可以给在线的某个用户发送聊天信息,也可以多人聊天,甚至可以给所有人广播。

2. 服务器模块设计

 

1>. 网络层

开发网络程序必须有一个稳定、高效的网络库框架。目前流行的基于C++的网络程序库有:

a. Boost ASIO

b. Libevent

c. unix socket API

这里极力推荐ASIO,两年来开发的多个服务器程序都是基于ASIO实现的,自己也非常的熟悉。自己也阅读过ASIO的源码,收获了一些非常宝贵的异步IO的设计技巧。网上有些人评论ASIO太大,太臃肿,我觉得其实不然。虽然ASIO为实现跨平台而增加了很多封装、宏,但是ASIO对应SOCKET的封装还是比较简单的。ASIO中最巧妙的就是所有IO模型都是建立在io_service上,这样网络层非常容易使用多线程。针对ASIO的分析详见前边的blog:http://www.cnblogs.com/zhiranok/archive/2011/09/04/boost_asio_io_service_CPP.html。使用ASIO还有一个好处是,你可以充分享受Boost库(如Lamda、shared_ptr、thread)带来的便捷,生产力立刻提升一个台阶。个人觉得使用ASIO需要有一定的模式基础。我也是用ASIO封装过一个网络层参见:

http://www.cnblogs.com/zhiranok/archive/2011/12/18/ffasio.html

当然喜欢搞底层的工程师都爱自己构建一个socket通讯库,这也无可厚非(即使有点重复造轮子),毕竟这样个人或者团队可以完全控制代码库的质量,出了问题也容易排查,而且也不需要太大的工作量。使用ASIO时我们就出现过问题,1.39版本的asio异步连接有bug,有非常小的概率回调函数不能被调用(大并发测试),更新到1-44就ok了。个人认为,对于一个团队,一个成熟的网络框架是成功的基石。

本示例中网络层传输协议非常简单,消息体body的长度(字符串形式)+\r\n + 消息体body,这样可以直接使用telnet测试本程序。

2>. 消息派发层

我曾使用过google protocol和facebook thrift,protocol只是封装了消息封装,不具有消息派发功能,thrift实际上是一个rpc框架,自动能够生成client代码或non blocking server框架代码。但是我们开发实时在线游戏后台程序都是基于消息的,所以开发一个类似protoco这样的东东还是很有意义的。用法是编写消息的idl文件,定义请求消息格式和响应消息格式。idl文件实际上也扮演了和client的接口描述文档角色。接下来使用idl 解析器分析idl 自动生成消息派发代码。

如在chat server示例中,我定义了chat.idl, 生成消息派发框架代码的方式是:

idl_generator.py idl/chat.idl include/msg_def.h

生成的代码文件为msg_def.h

其中idl文件定义为:

struct login_req_t
{
uint32 uid;
};

struct chat_to_some_req_t
{
array<uint32> dest_uids;
string content;
};

struct user_login_ret_t
{
uint32 uid;
};

struct user_logout_ret_t
{
uint32 uid;
};

struct online_list_ret_t
{
array<uint32> uids;
};

struct chat_content_ret_t
{
uint32 from_uid;
string content;
};

 

3> 领域逻辑层

领域逻辑尽量保证跟需求分析中建立的模型一致,DDD驱动。所以尽量不要集成太多网络层或消息解析层的代码。我的思路是将消息解析用idl解析器实现,网络层使用成熟的框架,这样我们只需集中精力测试逻辑层的正确即可。

本chat server只是要测试一下idl 解析器的功能,所以没有集成太多功能。

  主要代码片段为:

int chat_service_t::handle_broken(socket_ptr_t sock_)
{
uid_t* user = sock_->get_data<uid_t>();
if (NULL == user)
{
delete sock_;
return 0;
}

lock_guard_t lock(m_mutex);
m_clients.erase(*user);

user_logout_ret_t ret_msg;
ret_msg.uid = *user;
string json_msg = ret_msg.encode_json();
delete sock_;

map<uid_t, socket_ptr_t>::iterator it = m_clients.begin();
for (; it != m_clients.end(); ++it)
{
it->second->async_send(json_msg);
}
return 0;
}


int chat_service_t::handle_msg( const message_t& msg_, socket_ptr_t sock_)
{
try
{
m_msg_dispather.dispath(msg_.get_body() , sock_);
}
catch(exception& e)
{
sock_->async_send( " msg not supported! ");
logtrace((CHAT_SERVICE, " chat_service_t::handle_msg exception<%s> ", e.what()));
sock_->close();
}
return 0;
}

int chat_service_t::handle(shared_ptr_t<login_req_t> req_, socket_ptr_t sock_)
{
logtrace((CHAT_SERVICE, " chat_service_t::handle login_req_t uid<%u> ", req_->uid));
lock_guard_t lock(m_mutex);

pair<map<uid_t, socket_ptr_t>::iterator, bool> ret = m_clients.insert(make_pair(req_->uid, sock_));
if ( false == ret.second)
{
sock_->close();
return - 1;
}

uid_t* user = new uid_t(req_->uid);
sock_->set_data(user);

user_login_ret_t login_ret;
login_ret.uid = req_->uid;
string login_json = login_ret.encode_json();

online_list_ret_t online_list;

map<uid_t, socket_ptr_t>::iterator it = m_clients.begin();
for (; it != m_clients.end(); ++it)
{
online_list.uids.push_back(it->first);
it->second->async_send(login_json);
}

sock_->async_send(online_list.encode_json());
return 0;
}

int chat_service_t::handle(shared_ptr_t<chat_to_some_req_t> req_, socket_ptr_t sock_)
{
lock_guard_t lock(m_mutex);

chat_content_ret_t content_ret;
content_ret.from_uid = *sock_->get_data<uid_t>();
content_ret.content = req_->content;

string json_msg = content_ret.encode_json();
for (size_t i = 0; i < req_->dest_uids.size(); ++i)
{
m_clients[req_->dest_uids[i]]->async_send(json_msg);
}
return 0;
}

 完整代码参见:

https://ffown.googlecode.com/svn/trunk/example/chat_server

 3. 总结

  1. 网络层使用ffown,目前还没有socket管理模块主要是心跳功能,后续加入。

2. 日志直接使用printf完成,应该使用一个日志模块完成日志的格式化、输出等。

3. idl 消息派发框架支持者json字符串协议,二进制协议可以后续加入,而网络层应该具有压缩传输功能

4. 由于只是示例程序,client端我简单用python实现了一个。

 

 

 

 

 

 

 


原文链接:http://www.cnblogs.com/zhiranok/archive/2012/02/28/CPP_message_dispath.html


所属网站分类: 技术文章 > python文章

作者:23dh

链接: http://www.pythonheidong.com/blog/article/99229/

来源:python黑洞网 www.pythonheidong.com

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

13 0

赞一赞 or 踩一踩

收藏该文
已收藏

评论内容:(最多支持255个字符)

相似文章

  python 之 并发编程(非阻塞IO模型、I/O多路复用、socketserver的使用)

  Caused by SSLError("Can’t connect to HTTPS URL because the SSL module is not available)

  【SimpleITK】胸部CT数据3D space归一化,以及3D plot

  Learn Python the Hard Way : A Very Simple Introduction to the Terrifyingly Beautiful World o pdf下载

  Think Python : How to Think Like a Computer Scientist pdf下载

  python 全栈开发,Day89(sorted面试题,Pycharm配置支持vue语法,Vue基础语法,小清单练习)

  UBUNTU16 Qt中 C++调用Python import cv2时出错,求大佬解答

  关于Mac使用pip3时报错DistributionNotFound: The 'pip==18.0' distribution was not found and is required

  faster-rcnn错误信息 : tensorflow.python.framework.errors_impl.InvalidArgumentError: Assign requires shapes of both tensors to match. lhs shape= [21] rhs shape= [2]

  【2019.05】腾讯防水墙滑动验证码破解 python + selenium + OpenCV

优质资源排行榜

 python经典电子书大合集下载 下载次数 8108

 零基础java开发工程师视频教程全套,基础+进阶+项目实战(152G) 下载次数 7545

 零基础前端开发工程师视频教程全套,基础+进阶+项目实战(共120G) 下载次数 7439

 零基础大数据全套视频400G 下载次数 7002

 零基础php开发工程师视频教程全套,基础+进阶+项目实战(80G) 下载次数 6891

 零基础软件测试全套系统教程 下载次数 6502

 全套人工智能视频+pdf 下载次数 6436

 IOS全套视频教程 基础班+就业班 下载次数 4679

 编程小白的第一本python入门书(高清版)PDF下载 下载次数 3100

10  effective python编写高质量Python代码的59个有效方法 pdf下载 下载次数 3065

11  Python深度学习 pdf下载 下载次数 3044

12  使用python+pygame开发的小游戏《嗷大喵快跑》源码下载 下载次数 2998

13  python项目开发视频 下载次数 2997

14  python从入门到精通视频(全60集)python视频教程下载 下载次数 2994

15  黑马2017年java就业班全套视频教程 下载次数 2992

16  python实战项目 平铺图像板系统源码下载,适用于想要保存,标记和共享图像,视频和网页的用户 下载次数 2987

17  利用python实现程序内存监控脚本 下载次数 2986

18  树莓派Python编程指南 pdf下载 下载次数 2979

19  老男孩python自动化视频 下载次数 2979

20  老王python基础+进阶+项目视频教程 下载次数 2972

21  尚硅谷Go学科全套视频 下载次数 2972

22  某硅谷Python项目+AI课程+核心基础视频教程 下载次数 2967

23  Web前端实战精品课程 下载次数 2966

24  Python基础教程 pdf下载 下载次数 2966

25  tron python小游戏 下载次数 2962

26  [小甲鱼]零基础入门学习Python 下载次数 2959

27  老男孩python全栈开发15期 下载次数 2958

28  2017最新web前端开发完整视频教程附源码 下载次数 2948

29  最新全套完整JAVAWEB2018开发视频 下载次数 2926

30  Python算法教程_中文版 pdf下载 下载次数 2913

31  Spring boot实战视频6套下载 下载次数 2909

32  python全套视频十五期(116G) 下载次数 2901

33  Python项目实战 下载次数 2882

34  python全自动抢火车票教程-python视频教程下载 下载次数 2882

35  30个小时搞定Python网络爬虫 含源码 下载次数 2881

36  尚硅谷大数据之Hadoop视频 下载次数 2876

37  简明python教程 (A Byte of Python)pdf下载 下载次数 2873

38  Python A~B~C~ python视频教程下载 下载次数 2864

39  数据结构与算法视频(小甲鱼讲解-全) 下载次数 2863

40  web小程序表白天数倒计时源码下载 下载次数 2862

41  Python Cookbook第三版中文PDF下载高清完整扫描原版 下载次数 2862

42  python基础视频教程 下载次数 2862

43  Python高性能编程 pdf下载 下载次数 2862

44  go语言全套视频 下载次数 2853

45  利用Python进行数据分析 pdf下载 下载次数 2850

46  清华学霸尹成Python爬虫视频-ok 下载次数 2845

47  黑马前端36期最全视频和代码 下载次数 2841

48  2018最新全套web前端视频教程+源码下载 下载次数 2840

49  老男孩Python自动化开发12期 老男孩最强一期python高级运维开发课程 第二部分 70GB 下载次数 2832

50  流畅的Python PDF下载高清完整扫描原版 下载次数 2828