客户端架构设计的简单总结(转)

from:http://www.cppblog.com/weiym/archive/2014/07/26/207819.html

我们知道,客户端是相对服务端而言的,客户端程序相对普通应用程序,主要是增加了网络通讯功能。在这个移动和云存储的年代,大部分终端应用程序都有网络通讯功能, 所以都可以称为客户端。常见的客户端如浏览器,IM客户端, 网络会议客户端,邮件客户端,微博和微信客户端等...

通过观察,我们会发现所有的客户端基本是大同小异,都会包括一些相同的功能组件, 下面简单例举下:

通讯协议层

 

既然客户端都有网络功能,就会涉及到通讯方式和数据格式以及协议, 这三者不是完全独立,而是有机统一的。

首先说通讯方式,常见的通讯方式包括TCP,UDP, P2P和http(s), 很多时候我们不会用单一的通讯方式,而是多种通讯方式的结合。比如说TCP端口被封,走不通时,我们会转成尝试http(s)。IM中聊天文本走的是TCP, 由服务器转发,但是2个客户端之间的文件传输我们可能走的又是P2P了, 多个人之间的语音聊天, 我们走的又是UDP了。

其次说数据格式,常见的数据格式包括二进制编码,开源序列化协议和文本格式。
二进制一般是自定义的私有格式,通常对数值,我们会转成大头端,对字符串我们会用UTF8 编码,因为没有冗余数据,它的优点是不会浪费带宽;主要缺点是有硬编码的味道,不好扩充。
开源序列化协议这里主要是指google的protocal buffer,  现在很多公司都在用, 很多人基于它开发了自己的RPC框架。主要优点是数据小,使用简单而高效。
文本格式主要是指xml和json. 相对来说xml比较清晰和容易扩充,但是冗余数据比较多。json借助javascript对它语言层次的支持,感觉主要是前端人员使用的比较多。

最后再说协议,  协议和我们的应用相关联。比如邮件客户端,当然是走SMTP和POP3了; IM客户端的话,一般走XMPP了;  网络会议的话,可以走ITU的T.120协议, 也可以RFC 6501定义的XCON, 信令走SIP, 数据走RTP等。

通信协议层是整个客户端网络事件驱动的引擎,它可能会比较简单,也可能会很复杂。如果是基于XMPP的IM, 它可能会比较简单,因为基本上只需要一层文本协议的封包和解包就可以了。 当如果是基于T.120网络会议客户端,就会比较复杂,它数据包走的自定义的二机制格式,按照T.120协议的建议, 在通讯协议层又分了3层:TP, MCS和GCC。TP层主要封装数据传输的方式, 可以让上层无差别的区分TCP和http(s)。 MCS层主要提供多点传输功能, 它抽象出通道(channel)这个概念, 让不同session的数据进行逻辑隔离, 上层用户可以同时加入不同的通道来进行一对一和一对多的数据收发,并且通道中的数据有不同的优先级, 还有令牌这个机制。我们也可以在MCS层对数据进行加密和压缩, 还可以对上层的大数据包进行切包等。 GCC层主要封装会议的最基本逻辑,比如创建会议和加入session数据包的格式封装等, 让上层可以通过API调用而不用关心协议要求的数据包格式。不同的数据包会工作在不同的层次, 比如心跳包可能在底层TP层就被拦截了,它不要再往上层发,因为上面不用关心这个; 而有些数据包,则需要从底层往上层按照整个协议栈层层转发,当然每层都会剥离掉自己的协议头, 直至上层用户数据到达它的最终用户。

总之,通讯协议层封装了客户端和服务端的通讯方式及协议格式, 让上层用户不用关心底层的通信机制, 而只关注应用的接口事件。理论上我们可以在上层应用不做大调整的前提下,直接将网络会议客户端中的T.120协议成基于SIP的XCON。

功能组件

 

一个客户端程序通常是由很多功能模块组成,模块按功能来说可以分为基础组件和应用组件。

基础组件为应用组件提供的基础设施,基础组件是可以在不同的项目中重复使用的(比如界面控件库,2D渲染引擎Skia, 跨平台的网络和线程库等)。 
应用组件通常和我们当前的特定应用程序相关,比如我们的网络会议客户端包含的桌面共享模块, 文档共享模块,视频音频模块,文本聊天模块等。

应用模块本身分为带界面和无界面两种情况, 带界面的情况下我们通常会给组件提供一个容器窗口的句柄, 让组件自己在内部组织自己的界面。这种带界面的组件通常会为逻辑和界面的分离带来麻烦,在Window上实现一些半透明和动画效果也很难。 比如我们想提供跨平台的SDK来封装逻辑,这时我们会更倾向让应用组件采用无界面的模式,组件在跨平台层只封装逻辑和提供数据, 而把数据发到最上层界面层后再统一处理。

对功能组件我们的设计原则是尽量保持独立和可复用,最好能以仿COM方式动态升级而不用重新编译, 另外组件之间要保持层次性,避免双向或是循环依赖。

数据存储

 

客户端本身是处理和收发网络数据, 这里就涉及到对这些数据如何组织和存储的问题。这个通常会根据客户端的类型采用不同的处处理方式:
对于永久存储的数据,当然是保存成文件或是存入数据库,文件如xml, 数据库如ACCESS,  SQL server, mysql等。
临时数据当然是存入内存了,根据需要采用不同的数据结构, 组织格式如array,list, map, hashmap等。
还有一种是常见的数据保存方式是内存数据库,最常见是SQLite了, 内存数据库既能高效的分类保存大量数据, 又可以直接用基于SQL语句进行查询和处理, 比如foxmail客户端就是用SQLite存储的邮件信息。
还有一种是跨进程共享的数据,我们一般当然是内存映射文件了。比如我们有一个实时显示log的工具, 我们通常会在对方应用程序里分配共享内存的内存映射文件,所有的log都写到里面,然后在log工具程序里读取和显示。
当然还有一些数据可能存到网上去的, 常见的比如我们的云笔记, 这时数据分服务端数据和本地cache。

对于数据存储我们的设计原则是根据需要,选择简单高效的方式。比如我们在设计网络会议客户端时曾讨论要不要引入SQLite, 理想情况是引入内存数据库后各个组件和上层应用的数据都可以统一存储,采用数据驱动的方式,可以很方便的跟踪整个客户端的运行情况。但后来发现这种设计会把本来各自独立的组件通过数据库耦合在了一起,而且各组件的数据格式本身都很不要一样, 很难统一存储, 另外很多数据实际也只是临时数据, 没必要把简单的时间做复杂了。

客户端框架

 

客户端框架一般有两个作用:一是把所有的功能组件组织起来,进行统一的管理和展现; 二是实现整个客户端的主界面。客户端框架在协调各个组件时, 要注意避免让组件之间产生双向依赖, 而是应该让组件把事件通知给框架后由框架统一协调和处理, 所以客户端框架通常是整个客户端逻辑最复杂的部分。 一个好的客户端框架,通常会采用插件方式设计,可以动态插拔需要的组件。最好是可以根据服务端的配置, 动态下载和更新所需要的插件。

对于客户端框架, 我们的设计原则是低耦合和可扩展。基本上所有下层组件的改动都会影响到我们的客户端框架,客户的很多新需求和新组件也会导致框架产生坏味道, 这里我们设计时就要考虑如何让客户端框架能及时的适应这些变化。

界面库

客户端肯定会有界面,在Windows平台上,现在的界面大致分为以下几类:
基于Windows原始窗口控件句柄的C++ native 客户端, 基于.net的winform客户端,基于.net的WPF客户端,基于C++的DirectUI客户端, 以嵌入浏览器(如webkit)方式实现的客户端, 还有一类是基于Xaml的Metro客户端。

对于企业级大型安装应用,主要考虑的是开发效率,所以客户端还是以.net为主; 但是对于互联网企业, 更多的是要求客户端精简而高效, 所以还是以C++为主。 这里就设及到C++的两种界面库, 一种是基于windows窗口句柄和控件自绘机制的界面库,还有一中是基于DirectUI的界面库, 现在大一点的公司基本上都有自己的DirectUI界面库。基于修改Webkit方式实现的界面库可以通过Canvas和SVG动画等方式实现一些很炫的效果, 但是它和标准程序的用户体验还是有一定差距:一来web实现的控件跟Windows标准控件有很大不同, 二来web的流式布局和应用程序的网格布局也不一样。

对于界面,个人觉得这个东西变化实在太快了,所以我觉得应该尽量用界面和逻辑相分离的方式组织代码。

总结

对于客户端架构设计,个人觉得最大的原则就分层设计, 每层都封装一个概念并保持独立, 同时根据依赖倒置的原则, 站在上层客户的角度提供接口。软件工程里面的一条黄金定律:“任何问题都可以通过增加一个间接层来解决。

 

时间: 2024-08-08 07:21:46

客户端架构设计的简单总结(转)的相关文章

猿题库 iOS 客户端架构设计(原文地址:http://gracelancy.com/blog/2016/01/06/ape-ios-arch-design/)

猿题库 iOS 客户端架构设计 序 猿题库是一个拥有数千万用户的创业公司,从2013年题库项目起步到2015年,团队保持了极高的生产效率,使我们的产品完成了五个大版本和数十个小版本的高速迭代.在如此快速的开发过程中,如何保证代码的质量,降低后期维护的成本,以及为项目越来越快的版本迭代速度提供支持,成为了我们关注的重要问题.这篇文章将阐明我们在猿题库 iOS 客户端的架构设计. MVC MVC,Model-View-Controller,我们从这个古老而经典的设计模式入手.采用 MVC 这个架构的

一种Android客户端架构设计分享

转载请注明出处:http://blog.csdn.net/ahence/article/details/56678126 技术发展日新月异,业界各种Android客户端架构设计,五花八门,但我们不能简单地说哪种架构更好,因为脱离业务谈架构是没有任何意义的,适合业务的才是好架构.而架构也不是一成不变的,随着业务的发展,也许当初设计的架构已不足以支撑目前的业务,那么就需要改变之前的架构.接下来将分享下我们Android客户端的架构设计,在App的某个业务发展阶段或许有一些参考意义. 分层化与模块化

小梅科普:Unity客户端架构设计与网络游戏关键技术

目前利用Unity开发移动端游戏越来越多,不论是游戏公司还是独立开发者都需要在移动互联网时代发挥各自的技术优势,把自己的产品做到最好占领市场.本课程介绍的是基于Unity客户端框架设计以及关键技术3DAvatar换装和热更新技术实现以及Protobuf-net序列化和反序列化的运用,只有掌握了Unity开发的关键技术才能将其运用在游戏开发中,对于快速的开发游戏占领市场至关重要. 本课程以此项目的开发为讲解内容,以目前游戏开发的关键技术为依据,由浅入深循序渐进进行介绍,绝大部分的代码的编写都有相应

Unity客户端架构设计视频教程

课程讲师:海洋 课程分类:游戏开发 适合人群:中级 课时数量:20(42节)课时 更新程度:完毕 用到技术:Unity客户端,UI设计框架,Avatar换装,Protobuf-net等 涉及项目:搭建Unity客户端 UI设计框架以及Avatar换装和移动端热更新技术实现以及Protobuf-net在Unity中运用 咨询QQ:1609173918 下载链接:http://down.51cto.com/data/2037002 1.课程研发环境 开发工具:Unity4.6和VS2008 2.内容

Unity客户端架构设计与网络游戏关键技术(Avatar,热更新,Protobuf)

·  课程讲师:海洋 ·  课程分类:游戏开发 ·  适合人群:中级 ·  课时数量:20(42节)课时 ·  更新程度:完毕 ·  服务类型:C类(普通服务类课程) ·  用到技术:Unity客户端,UI设计框架,Avatar换装,Protobuf-net等 ·  涉及项目:搭建Unity客户端 UI设计框架以及Avatar换装和移动端热更新技术实现以及Protobuf-net在Unity中运用 对这个课程有兴趣的可以加我qq2748165793 1.课程研发环境 开发工具:Unity4.6和

手机游戏客户端架构设计

第一部分.模仿MVC模式.状态机制第二部分. UI设计(完成UI库设计,UI编辑器未完成)第三部分.动画(人物动画未完成,普通动画完成--工具CocosBuilder)第四部分.资源利用设计(ui资源.动画资源.精灵资源)第五部分.技能设计(本地计算)第六部分.战斗系统设计(回合制思路,移植世界OL战斗系统)第七部分.换装系统(思路.Demo设计完成)第八部分.任务系统设计第九部分.地图设计(完成设计,工具Tiled)第十部分.网络层设计(完成设计)第十一部分.消息中心设计(完成设计)第十二部分

客户端架构的简单总结

我们知道,客户端是相对服务端而言的,客户端程序相对普通应用程序,主要是增加了网络通讯功能.在这个移动和云存储的年代,大部分终端应用程序都有网络通讯功能, 所以都可以称为客户端.常见的客户端如浏览器,IM客户端, 网络会议客户端,邮件客户端,微博和微信客户端等... 通过观察,我们会发现所有的客户端基本是大同小异,都会包括一些相同的功能组件, 下面简单例举下: 通讯协议层 既然客户端都有网络功能,就会涉及到通讯方式和数据格式以及协议, 这三者不是完全独立,而是有机统一的. 首先说通讯方式,常见的通

分布式架构设计之电商平台

分布式架构设计之电商平台 何为软件架构?不同人的答案会有所不同,而我认为一个好的软件架构除了要具备业务功能外,还应该具备一定的高性能.高可用.高伸缩性及可拓展等非功能需求.而软件架构是由业务架构和技术架构两部分组成,因为有了业务结构才会催生出软件架构,进而来满足业务上的需求,所以,在做软件架构设计时,需要分为业务架构设计和技术软件架构设计,二者不可分离哦!那么,接下来就以本人实际工作中的电商平台为例,进行说明电商平台架构设计,因为不同行业产品系统不同业务不同,而催生的系统软件的实现要求及架构设计

MMORGP大型游戏设计与开发(客户端架构 part1 of vegine)

重写有些核心接口的时候,其实遇到了许多的问题,甚至一度的想过要放弃,但是最终还是坚持了下来.在客户端提供的这些接口中,可以清晰的看到客户端所依赖的各种模块的支持,以及各自之间的一些关联.下面只是介绍了vengine(微引擎)接口的基础模块框架,所谓的接口即对象设计中常见的Interface,为一个框架提供了清晰的规范支持. VEGINE FRAMEWORK 功能实现 该接口已全部实现,具体的实例只需要继承接口封装即可.上图只为简单的模块介绍,其实每个接口都有每个接口其特别的用处,这一点会在接下的