在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
前一篇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
3> 领域逻辑层 领域逻辑尽量保证跟需求分析中建立的模型一致,DDD驱动。所以尽量不要集成太多网络层或消息解析层的代码。我的思路是将消息解析用idl解析器实现,网络层使用成熟的框架,这样我们只需集中精力测试逻辑层的正确即可。 本chat server只是要测试一下idl 解析器的功能,所以没有集成太多功能。 主要代码片段为:
int chat_service_t::handle_broken(socket_ptr_t sock_) 完整代码参见: https://ffown.googlecode.com/svn/trunk/example/chat_server 3. 总结1. 网络层使用ffown,目前还没有socket管理模块主要是心跳功能,后续加入。 2. 日志直接使用printf完成,应该使用一个日志模块完成日志的格式化、输出等。 3. idl 消息派发框架支持者json字符串协议,二进制协议可以后续加入,而网络层应该具有压缩传输功能 4. 由于只是示例程序,client端我简单用python实现了一个。
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论