|
|
一、网络-数据包格式
1.TCP/IP,Socket
?找源码,例程
目前很多,书上有,网络上有
略作修改,很简单
?调试
OK
能够联通,收发消息。
2. 数据包格式
——简单应用,包格式简单:消息ID+长度+内容
聊天室
上传下载文件
——一般大型的应用,每种功能/命令定制一种消息格式?
1. 分功能类定义:用户接入,移动,状态变化,某个动作,定制不同类别的命令
2. 开始开发,1月,2月….,发现缺少消息?
3. 增加消息格式定义?开始修改前面的程序,原来消息的ID够分配吗?如果不够,麻烦
?我们的建议,尽量少定义消息格式:客户位置的变化可以解释为移动,客户状态数据的变化解释为状态变化,客户某个数据的变化解释为执行某个动作。修改客户的某个数据只需要一种格式,噢,减少了很多消息。
?面向数据定义消息格式,而不是面向功能定义消息格式,使开发的产品容易扩展。
——更加大型的应用,还是每种功能/命令定制一种消息格式?
1.功能越来越多,消息格式越来越负责,维护?真让人头疼。
2.开始没有考虑全,开发到中间,需要调整一些功能。因为有些消息格式是多个对象公用的,影响的范围太大了。
?我们建议,减少对象之间的消息关联,面向数据,功能由客户端或者服务器端解析。OK,一个对象增加或者修改功能,我只影响我自己。
?还是面向数据定义消息格式,而不是面向功能定义消息格式,使开发的产品容易扩展。
3. 如何处理组包和拆包
?对象类型很多,比如:不同装备,不同的实体(树、房屋、玩家、宠物)。每种对象都需要做一个组包和拆包函数,而且这些定义变化之后都需要修改这些函数,虽然建议很好,但是我觉得不好做,不像按照功能/命令定义消息格式来的直接,好理解。虽然后期维护工作量大,但我顾了那么多,需要很快看到结果。
不考虑以后的想法,对于一个成功的产品来说,特别是目前竞争如此激烈,是不可取的。
如何解决该问题呢?
?我们的建议,将对象属性的类型描述,单独定义为数据文件。程式通过解析该数据文件,可以得知每个对象在内存中存放的数据格式。从而,组包和拆包,针对多个对象,可以使用一个函数实现。
?喔,问题解决了一部分,将需要修改程序的问题转化为修改数据文件的问题,毕竟修改数据文件要容易一些,调试也容易。
?如何维护数据文件与真实对象的结构定义的一致性。
手工,很快能够实现,但是后继,随着对象的增多,工作量越来越大,反复检查,眼睛都花了,还是有错误。
?我们的建议,编写一工具,通过数据文件自动生成对象的结构定义。
4.数据包格式与带宽
?开发快完了,测试,麻烦了,带宽需求太高。
对于面向功能/命令的消息格式,重新检查每种消息格式,能否简化?该工作太难做了。
对于面向数据的消息格式,我们要开始考虑编码了。由于编码和解码只有一个函数,简单了。
?限制服务器用户数
服务器用户数都是有限的,数据包格式的设计,影响着服务器端可接入的用户数目。
单服务器的用户数,影响成本。
?我们建议消息以数据为中心,以方便进行消息的编码和解码。
5.版本升级
?增加了对象种类,消息格式,对象的功能做了修正。
开发类似一个引导程序的客户端,每次登录时检查版本,不一致则下载,OK,很好解决。变了一部分?全部下载,消息格式按照功能定义的,没有办法分割,我们不考虑,让用户忍受一段时间,大家都这样做,可以理解。
?增加了对象种类,消息格式,对象的功能做了修正。
对于面向数据的,哪些对象的数据格式变了,可以有针对的下载,喔,客户端启动快了一些。
?我们的建议,该问题不是很大,但是加快客户端的启动速度,更加能够为贴近用户。
?想增加一种NPC,比如执行某个任务:走到某个位置,找到附近的某个玩家,与玩家交谈。该NPC的行为可用脚本描述,也即可动态增加。
对于面向功能/命令的格式,需要定义新的消息?走到某个位置一个消息,找到玩家一个消息,与玩家交谈一个消息。发布新的游戏版本?代价也太大了。
对于面向数据的格式,增加一种NPC对象格式定义,包含:位置,找到玩家标志,与玩家交谈标志。服务器端脚本逻辑修改对应的数值,在客户端解析对象的动作。比如:玩家交谈标志变为1,则在客户端触发谈话的对话框。
?我们的建议,为使你的游戏容易动态扩展,选用面向数据的消息格式比面向功能的消息格式更加合适。
服务器和客户端数据格式定义
?采用面向数据的包格式,数据格式定义在服务器和客户端必须时刻保持一致。以便能够正确的组包和拆包。
?我们的建议,数据格式支持动态在线的变化,这样能够提供更大的灵活性,否则,只能够通过发布新版本,通过类似类似Boot的方式进行。目前在线的用户都被中断。
OK,采用面向数据的包格式果然好,我决定采用面向数据的包格式,接下来会遇到哪些问题呢?
二.网络-以数据为中心
1.以数据为中心的优缺点
?优点:简单易扩展
消息的组包拆包函数,不随着功能的增加或者改变而增加复杂性,应用程序的功能易于扩充
增加新的对象类型,不影响消息的组包和拆包。可以实现动态的增加对象类型。
消息的编码和解码易于优化,在需要考虑传输带宽的情况,更加容易维护。
?缺点:增加前期开发工作量
需要开发数据格式文件工具,而对于以功能为中心的,则不需要。
数据格式文件需要在服务器和客户端维持一致,实现上存在技术上的难度。虽然能够支持在线扩展功能,但是不像使用类似Boot程序的方法简单。
?优点:适于开发大型复杂的应用
对于大型复杂应用开发,前期的论证随着开发进行,不可避免的反复优化。以数据为中心的特点,使反复优化的工作量非常小。
对于增加的前期工作量,与其带来的好处来比,可以忽略。
2.数据格式文件的同步
?采用类似Boot的方式,每次数据格式的变化,都作为一个版本发布,可以考虑,但是对于采用脚本实现其功能的对象,发布新版本有些小题大做。
?客户与服务器端实现在线动态的同步。
该方法为应用程序提供了更大的灵活性,特别是与脚本语言配合;可以在线,动态的增加,修改对象的功能。
该方法可行的。
该方法实现具有一定的复杂性。
?我们的建议,数据格式文件的同步,是以数据为中心的大型应用的核心技术和关键问题,值得解决,以期提高应用程序的灵活性,是网络应用产品在市场上更加具有竞争力。
3.对象数据变了,如何处理
?对象的数据变了,需要组消息包,发送给客户端。整个对象的数据全部发送?增量发送?
对象全部数据发送实现简单,但是增加了对带宽的要求,增量发送实现复杂,可以降低带宽
?我们的建议,网络带宽是受限的,因此需要采用增量发送的方式。
?记录对象属性的变化?
采用增量发送的方式,需要记录属性的变化,在修改一个对象属性时,需要同时记录哪个属性发生的变化。
4.何时发送?
?按照功能/命令组织的消息包,产生之后就会进入发送队列进行发送。
?以数据为中心组织消息包,何时发送比较合适?
如果马上发送,喔,实现一个功能需要修改对象的几个数据。如果马上发送,则附加的开销比较多。
延迟发送,多少合适。
?我们的建议,该时间是以数据为中心的一个特点,与具体的应用相关。如果太短,则增加延迟。如果太长,则客户服务器之间的响应较慢。最好该时间可以配置。
5.数据变了,如何知道?
?收到消息,更新了对象的数据,如何映射为对象的功能?
由具体对象处理消息包,统一处理消息包,对变化的数据回调对象的处理函数。
?我们的建议,这两种方式都可以,但是考虑消息的编码和解码,采用回调的方式更加合理一些,这样对象的处理函数不需要关心消息的编码和解码。
?对象的属性变了,注册的回调函数得到了通知。
OK,现在能够映射功能了,不同的属性变化,可以映射为执行不同的功能。
如果这些功能采用脚本实现,可以在线增加修改,如果采用C/C++实现,对象属性变化时需要重新编译。
网络-对象的功能•1.C/C++/脚本语言
?对象的属性变化,需要通过回调的方式,映射为对象的功能
?采用C/C++语言实现
灵活,功能强大
不能够在线修改
?采用脚本语言实现
简单,
不易于调试
支持在线修改。
?我们的建议,对于基本功能,采用C/C++语言实现,对于逻辑,尽量采用脚本实现,除非有效率限制。
2.动态链接库
?对象的功能分模块,编译成动态链接库,一般常用的做法。
?如何注册回调函数?每个功能模块采用统一接口。
3.对象功能在客户端的同步。
?采用Boot类似的方式?
对于C/C++可接受,本来变化也意味着版本的升级。
对于脚本的,采用脚本的目的就是为了随时变化。有些小题大做。
?对于脚本描述的功能,需要支持在线更新。
?我们的建议,对于使用动态库定义的对象功能,采用Boot方式,启动的时候进行同步,而对于脚本定义的功能,需要支持在线更新。 |
|