2D仙侠网游
2D武侠网游
2D奇幻网游
2D Q版网游
2D网络游戏资讯
账号发放
最新网络游戏
抵制不良游戏 拒绝盗版游戏 注意自我保护 谨防受骗上当 适度游戏益脑 沉迷游戏伤身 合理安排时间 享受健康生活
Copyright 2009 - 2011
All Rights
Reserved.2D网络游戏引擎的设计与实现[2]
3课题研究的主要内容
游戏引擎是对一些底层或者其它的开发技术进行抽象,提供游戏开发的统一接口,
对资源、内存、动画、网络等方面进行管理,为游戏开发提供方便。游戏引擎实际上是
一个解释器,游戏开发者写下的游戏代码山游戏引擎进行解释,最后输出为一定的表现
早期的游戏开发效率较为低下,一方面是因为技术原因,另一方面是因为几乎每款东北大学硕士学位论文第一章绪论
游戏都要从头编写代码,造成了大量的重复劳动。渐渐地,一些有经验的开发者借用上
一款类似题材的游戏中的部分代码作为新游戏的基本框架,以节省开发时间和开发费
用。于是就慢慢产生了游戏引擎。
本文通过对网络通偷口图形图像处理的研究,设计并实现了一款具备网络通信、消
息处理、场景显示、角色行走与动作交互等功能的MMORPG类型的ZD引擎系统。
本文的主要内容如下:
通过对Wi ock技术、通信协议、通信方式以及MFC中的CSocket通信模型的研
究,在Wi ockAPI的基础上,对这些API进行重新封装和功能扩展,提出了一个网络
底层通信模型。
通过对网络通信方式和网络游戏中消息处理方法的研究,利用网络底层通信模型,
设计并实现了一个服务器端消息处理系统。
通过对客户端版本文件建立方法、文件接受与传输技术的研究,并借鉴MDS信息
摘要算法设计并实现了一个功能独立的客户端文件自动更新系统。
通过对位图调入、动画生成、角色移动与动作转换方法、复杂地图的生成与微缩、
碰撞检测技术、DirectX等技术的深入研究,设计了一系列图形处理、地图操作、自动
搜索路径的接口函数,并利用这些接口函数设计了一个动作交互操作模型。这些接口函
数具备这些功能:行走区域判定、支持模拟的场景高度,自动寻径,动态元素,旋转、
放缩、画面切换,支持图形化的标准界面控件,窗口模式运行,人物行走动作、声音与
模型的配合等等。东北大学硕士学位论文第二章引擎技术设计背景
第二章引擎设计技术背景
120游戏引擎设计背景
在以往的即时、对抗、竞技类游戏中所必需的要素就是真实感,而3D空间感画面
所表现出的高度拟真的视觉效果正是这些游戏所需要的,所以此类游戏的3D化是大势
所趋。而RPG游戏强调的是角色人物剧情和世界观的概念,所以单靠ZD游戏画面就可
以很好地表现这些必要游戏要素,并无需特地依赖3D化。
然而国内网游代理运营公司,在引进海外游戏上有点过于迷信3D潮流,前仆后继
而乐此不疲。那些公司决策者们好象总认为只要是3D网游即是大作的代名词,就能引
起不凡的市场的效应。然而空有震撼视觉效果无疑是难以持久吸引玩家的,丰富、动人
的情节才能成为永恒话题。
总的来说对于MMO妙G类型的游戏,3D网游相对ZD网游存在以下劣势:3D游
戏引擎开发技术上并不成熟和普及;由于过度追求画面质量导致玩家的互动性存在严重
缺陷;缺少琐碎的游戏设计所带来的游戏乐趣;采用鼠标和键盘方向键双重控制人物行
动和画面舒适性不及ZD网游;容易带来视觉疲劳;程序通常存在核心漏洞易被外挂造
成严重影响;硬件和网络要求较高。
因此现阶段对于MMoRPG类型的游戏,ZD引擎的开发从技术上来说更加成熟可
行,从市场效应来说也更能满足玩家的需求。
2游戏引擎的原理
游戏的引擎好比赛车的引擎,玩家所体验到的剧情、关卡、美工、音乐、操作等
内容都是由游戏的引擎直接控制的,它扮演着中场发动机的角色,把游戏中的所有元
素捆绑在一起,在后台指挥它们同时、有序地工作。简单地说,引擎就是用于控制所
有游戏功能的主程序,从计算碰撞、物理系统和物体的相对位置,到接受玩家的输入,
以及按照正确的音量输出声音等等〔J。,
3游戏引擎的处理过程框架
网络游戏的处理过程是这样的:首先是设置游戏的运行环境,对图形、声音、输入
以及网络进行初始化。然后对用户的输入进行检测以便根据玩家的意图来改变游戏的状东北大学硕士学位论文第二章引擎技术设计背景
态,然后对用户的输入请求进行处理。处理完后更新屏幕显示。当退出游戏时,清除初
始化时载入的所有图形、声音以及数据,释放内存。
处理过程如下图所示:
开开始游戏戏
清清理理理获取用户输入{{{
处处理用户输入入
更更新图形形
图2.1游戏引擎的处理过程框架
Fig.2.1Proce ofGameEngine
游戏初始化过程:首先连接远程服务器端,连接成功,则调用自动更新系统对文件
版本进行更新。
自动更新系统的工作过程是这样的:尝试连接更新系统服务器,为了加快下载的速
度,更新系统服务器通常有多个,如果连接失败则连接下一个更新系统服务器,直到连
接成功为止。然后获取版本信息文件的MDS值,通过检查MDS值来确定版本信息文件自
身有没有发生变化。如果有则取得版本信息文件,如果没有则无需任何更新直接进入游
进入游戏后,首先进行的是用户登录验证工作,客户端在发送用户信息进行登录请
求后,由服务器端消息处理系统进行判断,如果是第一次连接请求,则对登录消息进行
解析后发往数据库服务器进行用户验证,验证通过后,返回用户登录成功信息,用户进
入角色选择画面。然后创建角色或直接选择角色进入游戏服务器,处理过程与登录验证
处理过程类似。
进入游戏后,图形处理与动作交互系统对游戏的运行环境,图形、声音、输入以及
网络进行初始化。东北大学硕士学位论文第二章引擎技术设计背景
游戏初始化后,如果游戏没有结束,获取用户输入,这个用户输入包括本地客户端
的输入和远程客户端的输入。如果是本地客户端的输入,则直接调用图形处理与动作交
互系统程序中相关的API对用户的输入请求进行处理,并同时将处理结果发往服务器端。
如果是远程客户端的用户输入,则服务器端消息处理系统对该客户端的用户输入信息进
行解析然后将该消息发送过来,在本地机器上对远程客户端的输入进行模拟处理。处理
完用户请求后对屏幕图形进行更新显示。
4客户机/服务器结构
在C/s(客户机/服务器)结构中,客户机只与服务器进行通信,而不与其他客户端
进行通信。客户机发送请求到中心服务器,中心服务器处理请求并发回应答信息。如果
玩家想要给另一个玩家发送一个消息,首先他必须发送消息到服务器,然后服务器将消
息转发给目的玩家。这种通信方式拥有较高的安全性,同时也允许有更多的玩家。
C/S结构的分工情况是这样的:客户机应用程序负责图形更新,服务器负责处理请
求和应答。服务器端的请求应答体系模型是这样的:
编…烹…撬
……………………………………………………………………{{{请求移动指令}动的命令,始移动}移动的指令,更堑屏幕}又又玩玩玩家A向服务器发送-----玩家A接受到允许移移周围玩家接受到玩家AAAAA请请请求移动指令令动的命令,开始移动动移动的指令,更新屏幕幕幕
服服务器接受到移动请求求求服务器发送允许许
并并检查到前方无障碍碍碍移动指令令
图2.2请求和应答体系模型
2SystemArchiteeUrteofRequestnadAw er
5引擎的存在形式一动态链接库
整个游戏的引擎存放在多个动态链接库文件中,开发人员通过对这些动态链接库的东北大学硕士学位论文第二章引擎技术设计背景
调用来实现在本引擎平台上开发游戏的过程。
动态链接库(DLL)是从C语言函数库和Pasacl库单元的概念发展而来的。所有的C
语言标准库函数都存放在某一函数库中,同时用户也可以用LBI程序创建自己的函数
库。在链接应用程序的过程中,链接器从库文件中拷贝程序调用的函数代码,并把这些
函数代码添加到可执行文件中。但随着Windows这样的多任务环境的出现,函数库的
方法显得过于累赘。如果为了完成屏幕输出、消息处理、内存管理、对话框等操作,每
个程序都不得不拥有自己的函数,那么Windows程序将变得非常庞大。Windows的发
展要求允许同时运行的几个程序共享一组函数的单一拷贝。动态链接库就是在这种情况
下出现的。动态链接库不用重复编译或链接,一旦装入内存,DLL函数可以被系统中的
任何正在运行的应用程序软件所使用,而不必再将DLL函数的另一拷贝装入内存。
1动态链接库的工作原理
对于常规的函数库,链接器从中拷贝它需要的所有库函数,并把确切的函数地址传
送给调用这些函数的程序。而对于DLL,函数储存在一个独立的动态链接库文件中。在
创建WindowS程序时,链接过程并不把DLL文件链接到程序上。直到程序运行并调用
一个DLL中的函数时,该程序才要求这个函数的地址。此时Windows才在DLL中寻找
被调用函数,并把它的地址传送给调用程序。采用这种方法,DLL达到了复用代码的极
动态链接库的另一个方便之处是对动态链接库中函数的修改可以自动传播到所有
调用它的程序中,而不必对程序作任何改动或处理。
DLL不仅提供了函数重用的机制,而且提供了数据共享的机制。任何应用程序都可
以共享由装入内存的DLL管理的内存资源块。只包含共享数据的DLL称为资源文件。
如Windows的字体文件等。
2动态链接库的调用
有两种方法可用于调用一个储存在DLL中的过程。
()l静态调用或显式装载
使用一个外部声明子句,使DLL在应用程序开始执行前即被装入。例如:ufnctino
I tr(sourcest::Pehar:eheck:ehar);Integer:arr:extemalusestr,:使用这种方法,程序无
法在运行时间里决定DLL的调用。假如一个特定的DLL在运行时无法使用,则应用程
序将无法执行。
在静态调用一个DLL的过程或函数时,xeetmal指示增加到过程或函数的声明语句
中。被调用的过程或函数必须采用远调用模式。这可以使用arf过程指示或一个{$F+}
编译指示。东北大学硕士学位论文第二章引擎技术设计背景
(2)动态调用或隐式装载
使用windowsAPI函数LoadLibrya和GctProcAddre 可以实现在运行时间里动态
装载DLL并调用其中的过程。
若程序只在其中的一部分调用DLL的过程,或者程序使用哪个DLL,调用其中的
哪个过程需要根据程序运行的实际状态来判断,那么使用动态调用就是一个很好的选
使用动态调用,即使装载一个DLL失败了,程序仍能继续运行。
动态调用中使用的WindowsAPI函数主要有三个,即:Loadibiryar,GePtrocAddre 和Freelibaryr。
①Lodabljryar:把指定库模块装入内存
语法为:ufnetionLoadlibra叮(LibFil酬ame:PCh)ar:THnadle:
LibFielName指定了要装载DLL的文件名,如果LibFielName没有包含一个路径,
则Windows按下述顺序进行查找:
(a)当前目录;
(b)Windows目录(包含win.com的目录)。函数GetwindowDiereto理返回这一目录
的路径;
(e)诚ndows系统目录(包含系统文件如gdi.xee的目录)。函数Getsystelloireeto汀
返回这一目录的路径;
(d)包含当前任务可执行文件的目录。利用函数GeMtoudelFielNmae可以返回这一
目录的路径;
()e列在PAT,H环境变量中的目录;
()f网络的映象目录列表。
如果函数执行成功,则返回装载库模块的实例句柄。否则,返回一个小于
HNISTANCEERROR的错误代码。
②GePtorcAddresS:捡取给定模块中函数的地址
语法为:允nctionGe企rocAddre (Moudle:THnadle:PoreName:PChar):TFaProre:
Moudel包含被调用的函数库模块的句柄,这个值由Loadlibrayr返回。如果把
Mdoule设置为nil,则表示要引用当前模块。PorcName是指向含有函数名的以nil结尾
的字符串的指针,或者也可以是函数的次序值。如果PorcName参数是次序值,则如果
该次序值的函数在模块中并不存在时,GePtorcAddresS仍返回一个非nil的值。这将引
起混乱。因此大部分情况下用函数名是一种更好的选择。如果用函数名,则函数名的
拼写必须与动态链接库文件EXPOTRS节中的对应拼写相一致。
如果GetProcAddre 执行成功,则返回模块中函数入口处的地址,否则返回nil。
③Freehbryar:从内存中移出库模块
语法为:proceudreFreelibr脚(Moudle:THnadle);东北大学硕士学位论文第二章引擎技术设计背景
Mdoule为库模块的句柄。这个值由Loadlibrayr返回。
由于库模块在内存中只装载一次,.因而调用Freelibaryr首先使库模块的引用计数减
一。如果引用计数减为O,则卸出该模块。
每调用一次Loadlbiaryr就应调用一次FreeLibyar,以保证不会有多余的库模块在应
用程序结束后仍留在内存中。
6引擎构成
游戏引擎和框架的抽象一直是游戏制作中的一个关键问题,其核心问题是如何令
抽象好的引擎具有更好的适应性。
游戏按功能分为:消息处理系统、场景显示及行走系统、动作交互系统三大主要
部分。其中又以消息处理系统为核心模块,其余部分紧紧围绕它运行。
基于前面的C/S结构和游戏引擎的处理过程框架,本文设计了一个如图.23所示的
引擎基本框架:
应用程序
弓I擎}消J息处理系统}}图形管理}}规贝。系统
物物件系统统统地图系统统统路径搜索索索其他他
底层引擎
图.23游戏引擎基本框架
3GameEngineSystem
7本引擎的功能分析
1消息处理系统
消息处理系统是游戏的核心部分。游戏用到的消息处理系统先等待消息,然后根据
收到的消息转到相应的函数进行处理。比如:角色A碰到敌人后开始动作交互,东北大学硕士学位论文第二章引擎技术设计背景
同时将该动作交互数据发往服务器,由服务器验证后发给周围的玩家,周围的玩家B调
用消息处理系统对这个消息进行解析,随后在本地调用相应的模块模拟角色A的动作交
互动作。消息处理的大体框架如下:
DWORDMe age;//消息变量
Wil1Main()//进入程序
{初始化主窗口;
while(1)//消息循环
{switch(Me age)
{aces行走消息:行走模块;()
aces动作交互消息:动作交互模块();
acse事件消息:事件模块;()
本引擎提供的消息处理系统主要是服务器端的消息处理过程。
包含2部分:网络通信底层模块和服务器端消息处理模块。网络通信底层模块通过
对Socket的I函数进行封装和功能扩展,使得在调用时更加方便。服务器端消息处
理模块实现了服务器端消息处理的整个过程,开发人员在使用本引擎模块时,可根据自
己的需要继承并重写HnadieMe gaeBueff()r接口函数,可以处理自己定义的各个消息类
2图形处理与动作交互系统
图形处理与动作交互系统是客户端程序处理的主要部分,也是直接与玩家进行交互
的部分。
加入DirectX处理后的图形处理过程:在内存中开辟一到两个屏幕缓存区,事先把
即将显示的图象数据准备在缓存区内,然后一次性把它们传送到主屏幕缓冲区内。
行走与动作交互处理过程如下:根据角色的当前位置与目标位置,利用计算位置差
的方法来判断角色的移动方向,然后调用向该方向移动的系列图片,以固定的步长向该
位置移动,动作交互时,根据碰撞检测的判断,调整双方的方位将动作转为动作交互,
同时播放动作交互的W***,并跟踪任务状态的变化在界面上显示出来。
本文根据功能划分的不同为图形处理与动作交互系统设计了三个应用程序接口模
块:图形处理模块、路径搜索模块和地图编辑模块。这三个部分基本实现了客户端场景
显示、行走区域判定,自动搜索路径,复杂地图与微缩地图生成,碰撞检测等功能。最
后利用这三个模块的API函数实现了一个小型的动作交互模型。东北大学硕士学位论文第二章引擎技术设计背景
3自动更新系统
自动更新系统是网络游戏设计中的一个重要组成部分。正是由于程序内容不断更
新,才使得网游的持续可玩性较强。同时这个系统也方便了开发人员做更新和维护。
自动更新系统的处理流程如下:首先在服务器端利用文件版本处理模块建立客户端
版本,客户端连接上服务器以后,获取关于文件最新版本的数据,比较本地版本和最新
版本信息文件的MDS值,发现不同后服务器就把最新的文件传送到客户端,并更新版
本文设计的自动更新系统模块由三个子模块组成:文件版本管理模块、文件传输服
务器模块和客户端接受文件传输模块。这是一个独立的引擎模块,实现了游戏客户端更
新版本的整个过程。东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
第三章消息处理与更新系统的设计与实现
网络游戏中需要处理的内容很多,如玩家网络数据的传输、玩家命令的解析、游戏
规则的实现等。因此游戏服务器需要分层来设计,使整体结构更加清晰。游戏服务器分
3层来设计,如图3.1所示。最底层是网络层,负责网络数据的接受与发送。中间层是
命令处理层,负责命令的接受、发送与解析。上层是最复杂的虚拟世界层,在这一层中,
游戏中的各种物体按既定的规则运行着,并发生交互关系。
虚虚拟世界层(物件模型)))
命命令处理层(命令分析器)))
网网络层层
图3.1游戏服务器
Fig.3.1Gamesevrer
游戏世界中的许多物体例如道具、玩家和NPC等等,这些物体之间的相互作用构
成了一个复杂的虚拟世界。
1消息处理系统设计
网络游戏的网络部分实际上就是一个消息处理的过程,本消息处理系统包含2部
分:网络通信底层模块和服务器端消息处理模块。网络通信底层模块通过对Socket的
API函数进行封装和处理,使得在调用时更加方便。服务器端消息处理模块实现了服
务器端消息处理的整个过程,开发人员在使用本引擎模块时,可根据自己的需要重写
HandleMe ageBueffr()方法来实现自己需要的功能。
了网络通信底层模块
Sockct是一套用于网络数据传输的编程接口。它位于网络通信协议和应用程序之
间。使用Socket开发网络通信程序可以避免直接面对复杂的网络通信协议,加快开发
速度,并可以做到跨协议与跨平台开发。
TCP连接的过程东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
在TCP应用中,为了建立一个网络连接实例(I tnaec)的服务器端,只需设置本地
服务端日号,然后服务器一调用方法Listne进入阻塞状态,等待来自客户的连接请求。与
此对应的客户端不但要将Wi ock的属性RemoteHost置为服务器的名称(PI地址或网
络代号),还应设置服务器所***的相应服务的端口号(RemotPeort),如FTP服务在
21号端口,HTTP在80号端口等。然后调用方法wi oc.kco ect向服务器发出请求。
服务器接收到客户请求时,事件CnonectinoReuqest将被触发。如服务器愿意提供服务,
则可调用AccPet方法接受连接。
图3.2和图3.3分别是服务器端和客户端TCP连接的基本过程:
服务器端:
设设置本地服务端口号号
服服务器进入***状态态
收收到客户连接请求求
检检查50。ket状态态
接接受客户请求求
接接收/发送数据据
处处理客户数据据
关关l闹wi oCkkk
图3.2服务器端TCP连接过程
Fig.3.2ConrieetionPoree ofsevrerByTCP东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
客户端:
开始连接
设置服务器相应服务端口号
向服务器发出连接请求
服服务器响应连接接
进进行数据传输输
关关闭wi oCkkk
图3.3客户端TCP连接过程
3ComreetionProce ofClientByTCP
2wi oe伙基本的AP!
(l)WSAStartup():连结应用程序与WindowsSoeketDLL的第一个函教。
说明:此函数是应用程序调用wnidowsSokcetDLL函数中的第一个,他唯有此函
数呼叫成功俊,才可以再调用其他WnidowSSocketDLL的函数。
(2)WSAClea tl():结束WindowsSoeketDLL的使用。
说明:当应用程序不再需要使用WnidowsSocketDLL时,需要调用此函数来注销
使用,以便释放其占用的资源。
(3)soeket():建立Soeket。
说明:此函数用来建立一socket描述字,并为此Socket建立其所使翔的资源。
(4)elosesocket():关闭某一Soeket。
说明:此一函数是用来关闭某一Socket。
(5)bind():将一本地地址与一个SOCKET描述字连接在一起。
说明:此函数在服务程序上使用,是调用***函数sIitneO必须要调用的)函数。
(6)listen():设定soeket为***状态,准备被连接。东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
说明:此函数在服务程序上使用,来设定Socket进入***状态,并设定最多可有
多少个在未真正完成连接前的客户端的连接要求。
(7)acecPt:()接受某二Socket的连接要求,以完成面向连接的客户端Socket的连
接请求。
说明:服务端应用程序调用此函数来接受客户端Socket连接请求,acecPto函数的
返回值为一新的Socket,新Sockct就可用来在服务端和客户端之间的信息传递接收,
而原来Socket仍然可以接收其他客户端的连接要求。
(8)c0 eo()t:要求连接某一Socket到指定的网络上服务端。
说明:此函数用在客户端,用来向服务端要求建立连接。当连接建立完成俊,客
厂端即目J一利用此Socket来与服务端进行信息传递。
(9)reev():从面n{]连接的Soeket接收信息。
说明:此函数用来从面向连接的Socket接收信息。
(10)send():使用面向连接的Soeket发送信息。
说明:此函数用来从面向连接的Socket发送信息。
(11)wsAAsyneselect():要求某一socket有事件(event)发生时通知使用者。
说明:此函数用来请求WnidowSSocketSDLL为窗口句柄发一条消息一无论它何
时检测到由EIvent参数指明的网络事件。要发送的消息由wMsg参数标明.被通知的套
接口由S标识。本函数自动将套接口设置为非阻塞模式。
EIvent参数由下面列出的值组成。
FDREAD欲接收读准备好的通知。
FDWRITE欲接收写准备好的通知。
FDOOB欲接收带边数据到达的通知。
FDACCEPT欲接收将要连接的通知。
FDCONNECT欲接收已连接好的通知。
FDCLOSE欲接收套接口关闭的通知
3网络通信底层模块的功能需求
网络通信底层模块必须完成从连接到数据通信的一系列过程,它的主要功能如下:
发送数据、接受数据、请求连接、接受连接、绑定地址、***、可读可写判断、异常检
测判断、设置非阻塞(或阻塞)状态等。
4网络通信底层模块的设计
Socket的API是以函数形式提供的,本模块对这些API函数进行了封装,并对这
些API函数的功能进行了扩展。使之在应用时更加方便简洁。本模块不是一个具备独东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
立引擎功能的模块,开发人员需要自己根据TCP连接的过程,使用本模块的API函数
组建自己的通信模型。函数设计如下:
表3.1网络通信底层接口函数设计
Table3.1APIofNewtorkCorresPond
函函数原型型函数功能能
IIInitia!ize(intportoeol)))初始化网络通信协议和接受网络消息方式(阻塞和非阻阻
塞塞塞)))
on一:eet(e]:a一*szAddr,intPort,,对远端的协议地址进行解析,建立Socket连接接
。。I 一gnedlongIP)))))
BBB一ndAddr(ellar*一P,IntPott)))指定网络通信对象,给Socket分配一个协议地址址
LLL一sten()))***Socket连接状态态
AAAeeePt()))接受一条新的Socket连接接
666e比。eaIAddl(e}lal水add几shorttt取得本地PI地址和端口号号
***Port,un、,gnedlong*iP)))))
*port,u ignedlong*ip)
Send(ehar*bu,fintIen)
SetNonBloeking()
SendOT(ellal*bu双intlen.
SOCKADDR_IN*addr)
ReevF,onl(ehar*bL,,fint
len,SOCKADDRIN*addr,一nt
*addrlen)
setsel记B。一士化一S一ze(Intlen)
SetReevBL:阮rslze(intlen)
Reev(ehar*bL,仁l一飞tlen)
HasExeept(少
Ca,iRead()
Canwrite()
Close()
在个Socket上发送数据
设置接受网络消息方式(阻塞和非阻塞)
利用数据报方式进行发送数据
利用数据报方式进行接受数据
重新设置SOCKET发送消息缓冲区的大小
重新设置SOCKET接受消息缓冲区的大小
在某个Socket上接受数据
Socket的异常检测
进行可读检测
进行可写检测
关闭Soeket连接东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
5网络通信底层模块的函数实现
Initialize(intprotoeol)函数用来初始化socket连接,在初始化时设定网络通信协议类
型,是uDP还是TcP。另外初始化时还调用esNtoBn1ocking()方法设置接受网络消息的
方式是阻塞还是非阻塞。
BindAddr(char*iP,intPort)实现了对bind(处socket,(SOCKADDR*)&am addrLoea一,Sizeo(fad由Local))函数的封装,soekdf是一个socket描述符,my-addr是一个
指向包含有本机PI地址及端口号等信息的sockdadr类型的指针;dadretn常被设置为
sizeo(fsturetsoekaddr)。本函数通过对m犯add.rsin一port和my-ad.drsi--nad.dr--asddr的赋值
来获取地址信息。
LisetllO实现对接口函数slitneo的封装,当***失败时,将错误信息写入日志。
eo eet(cha:*szAd,drintport,u igned一0119ip)实现了对API函数
co eet(m_soeket,(soeKADDR*)&am addrRemote,sizeo(faddrRemote)的封装。通过对
m--ydadr
Sni夕ort和m又dad.rSni_dadr.礼dadr的赋值来获取地址信息。连接失败时,将失
败信息写入日志。
Aecept()函数封装了accept(intsockdf,void*ad,drint*addrlen)。成功连接时,连接数
加1(用于和最大连接数比较)。
GetLoealAddr(char*add,rshort*port,u ignedlong*ip)和GetRemoteAddr(ehar*add,r
short*port,u i罗edlong*ip)分别封装了getsocknmae(--msoeket,(SOCKADDR*)&am addrLocal,&am len)和gePteenrame(--msocket,(soekaddr*)&am addrRemote,(soekle--nt*)&am len)
并通过转换后分别返回本地PI地址、端口号和远程地址、端口号。
Send(char*bu,fintlen)、Reev(char*bu,fintlen)、SendOT(ehar*bu,fintlen,
SOCKADD--RIN*addr)和RecvFrom(ehar*bu,fintlen,SOCKADD--RNI*addr,int
*addrlen)分别实现了对send(--msoeket,bu,flon,0)、reev(--msoeket,bu,flen,0)、
sendto(m_socket,bu,flen,0,(SOCKADDR*)add,rsizeo(fSOCKADD凡NI))和recvrfom
(业soeket,bu,flen,o,(SOeKADnR*)add,r(soekle--nt*)addrlen)的封装。在接受或发送数据
前分别调用CnaWrti(e)和CnaRedao进行可写、可读检测。检测成功后进行数据传输,
返回实际发送的数据字节长度或在出现发送错误时返回一1。
setNonBlocking()封装了loeTLsoe跳T(处socket,FIONBIO,&am asr),通过改变a笔
的值来设定阻塞和非阻塞方式。
setsendBueffrsize(intlen)和se血evBueffrsize(intlen)通过改变
setsockopt(--msoeket,SoL_sOCKE,TS--OB呱(ehar*)&am len,sizeo(flen))函数中BUF的类型
为50SNDB班和50RCvBUF来设定缓冲区的大小。
另外在soeket的I函数中,intSeleet(ndfs,readdfs,writedfs,exeeptdfs,timeout)函
数用来检测Socket的状态。其中ndfs表示Wi 邺k中此函数无意义;raeddfs表示进行东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
可读检测的Socket集合,wrtiedfs表示进行可写检测的Socket集合,xeecPtdfs表示异常
检测的soeket集合。本模块中的函数Canwrite(),Ca叹ead()和HasExcept()分别通过调
用selec(t…)函数,并对es1ec(t…)中参数赋予不同的值,来完成各自的功能。
2消息处理模块
常用的接受网络消息的方式有:()l阻塞式的接受。(2)异步的非阻塞的接受。如果
使用方式()l,那么接受网络消息的函数就会一直等待消息,除非到达指定的时间,与
此同时,程序的运行也停在此处。使用方式(2)接受消息的函数只是去消息缓冲区里检
查一下是否有新的消息,然后马上返回,中间不存在等待的过程。
1异步模式
阻塞模式也称为同步模式,在这种模式下,Wnisock函数直到全部操作完成后才返
回。比如要接收数据包时,必须等到对方将数据包发送过来为止,调用Wnisoclk函数的
线程在这期间是被挂起的,所以程序看起来好像是停止响应了。显然,要以这种方式执
行wnisock函数的话,几乎每个函数的使用都会违反1/10秒规则,所以必须考虑在不
同的线程中执行每个WniS邻k函数。
wnisock为所有的函数提供了非阻塞模式的版本,非阻塞模式又称异步模式,在这
种模式下,一个函数执行后会立即返回,即使是操作还没有全部完成,但是当函数最终
完成操作的时候,Wnisock接口合通过某种形式(如窗口消息)通知应用程序,显然这
种方式非常适合于WnidowS下的消息驱动体系。
Wnisock通过异步选择函数WSAAy cSe1ec()t来实现非阻塞通信。方法是由该函数
指定某种网络事件,如有数据到达、可以发送数据、有程序连接请求等,当被指定的网
络事件发生时,由wi ock对程序发送由程序事先约定的消息。程序中就可以根据这些
消启、做相应的处理。
格式如下:
intWSAsyneseleet(SOCKETs,HWNDhwnd,u ingedintwMsg,longIEve恤)t;
Socket在这个函数中被自动设成非阻塞方式,hwnd是接收Wnisock消,急的窗口句
柄,非阻塞方式下wMgs是向窗口发出消息名称,用户可以任意定义。EIventl是被指定
的网络事件。当被指定的网络事件发生时,程序将收到消息,在消息的MSG结构体中,
Mesasge项就是被规定的消息名称wMgs,PIaram即为网络事件名称。
在异步模式下,Clinet端和Sevrer端连接过程如下:
(1)Sevrer端接受Client端的连接
由于Sevrer端的socket是设定为异步模式,且是针对FD一ACCEPT事件的,所以
当Client请求连接时,Sevrer端的hwnd视窗会收到Wi ockStaek进来的一个东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
AsYNC_EVENT的信J自、。这时应该先利用wsAGETsELEcTERRoR(PIaram)来检查
是否有错误;并由WSAGETSELECTERROR(PIaram)得知是什么事件发生;然后再
}啊叫相关的函数来处理此事件。对应于FD_AccEPT的函数acecPto来建立esvrer端的
(2)elient端向Sevrer端主动建立连接
Client首先还是呼叫wsAstaurtp()函数来与wi ockstack建立关系;然后同样呼叫
soeket()来建立一个TCPsoekot(来连接Sevrer端的TCPSoeket)。和Sevrer端的Soeket
不同的是,Client端的Soeket可以呼叫bind()函数,由自己来指定IP地址以及端口号;
也可以由Wi ockStack来自动设定PI地址及端口号(此动作在呼叫oc ecto函数时会由
willsoek()系统来完成)。
2消息处理模块的设计
由于采用多线程的方法,在大型多人在线游戏中,线程数量巨大,管理非常复杂,
而且线程同步问题不易解决,因此下面采用异步的非阻塞的方式接受消息并处理。
本模块设计的原理是这样的:服务器端为每一个成功连接的客户端创建一个Socket
连接,服务器接受客户端消息的过程在每一个Socket连接里进行。然后将所有客户端消
启、存入主线程缓冲区中,处理消息的过程统一在主线程中进行。所以消息的处理过程仍
然遵循异步模式。接口函数设计如下:
表3.2消息处理模块接口函数设计
Table3.2APIofPoree ingMe age
函函数原型型函数功能能
CCCreateserVersocket(u ignedintPort)))创建***Sock以的过程程
EEEndserversoeket()))清除所有客户端的连接接
AAAddNewPlayer()))添加新的客户端连接,为每个客户端分配一个IDDD
DDDeletePlayer(CSocket*es_Player)))删除指定客户端的连接接
OOOnAecePt(intErrorCode)))接受客户端连接时触发发
OOOnReeeive(intErroCrode)))接受消息并放入消息缓冲队列列
GGGetNewPlayeNrame(CSoekettt接受新登录的客户端的玩家信息息
***es_Newplayer)))))
SSSendOTAllMsg(ehar*eh_ChatMsg,CReeeivvv对要发送的公告进行拼接,并发送给所有玩家家
eeesocket*es__Player)东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
续表3.2消息处理模块接口函数设计
Table3.2APIofProee ingMe age
函函数原型型函数功能能
GGGetMe ageForlllPlayersoeket()))把消息保存到自定义的缓冲记录里里
OOOnldle()))当应用程序空闲时调用用
HHHandleMe ageBueffr()))处理消息缓冲(主要函数,引用时可对它重载)))
.3消息处理模块的函数实现CreateseVrersoeket(u ignedintport)创建一个指定端口的socket,并在这个端口上进行***Endserversoeket戈),使用delete命令删除所有客户端的连接。OnAccPe(tintErrorCode)这个函数是当有新的客户端连接时触发,通过调用AddNewPlaye(r)函数为新连接的客户端分配一个唯一的标识ID。OnRecovie(nitErrorCode)对每一个客户端,***到消息来时,先判断是否己经登录,如果没有登录,则为登录消息,通过调用GeNtewpl叮eNrmae(CSoeket*csjewplayer)进行登录验证,如果己经登录则将消息保存在缓冲区里。AdNdewPlyaerO,当AccePt()接受到有新的玩家连接后,为该玩家分配一个唯一的标识ID,并将该ID和Socket指针对应起来。以后就可以通过处理Socket指针来处理对应ID的玩家的消息。并对AccPe()t函数求得的Socket进行地址解析,求出该玩家的IP地址。GetNewplayeNrame(CSocket*cs_Newplayer),这个函数是在新玩家登录时调用的。当有消息到来时,在onReeeive(intErrorCode)函数中判断用户是否己经登录过,如果没有登录,那么这条消息就是登录消息。然后调用GeNtewPlyaeNram(eCSocket*cs一NewPlyae)r函数对该消息进行解析,然后将解析后的玩家数据发送到数据库进行验证。Deleteplayer(CSoeket*cs一Player),当玩家退出时,服务器删除指定玩家的连接,当玩家断开与服务器的连接后,由于玩家ID是预留位置的数组中下标号;所以清除一个玩家后会将后面的玩家的数组数据前移一个位置。例如:ofr(inti一pl盯eNro:i< layerCount一l:i++){Playerlnof【i」.esPlayerlnof[i].cs_Clientptr=plyaerlnof[i+1」·c--sClienPttr:_Clientprt一> layeNro一:}HandelMe gaBeueff()r,设置一个消息查看的循环,当消息缓冲队列中存在消息时,依次取出消息并解析出消息的类型,然后针对不同的消息类型,调用不同的方法进行处理。本引擎只列出了常用的几种消息的处理方法。在应用的时候可以对该方法进行重载。东北大学硕士学位论文第三章消息处理与更新系统的设计与实现GetMe ageFro耐layersoeket(),将每一个客户端的消息保存到自定义缓冲区内。24消息处理模块的处理流程(l)在设计消息处理过程中,服务器端与客户端的消息采用相同的结构体。例如:登录消息:ytPedefsturettag_Loginlnof{e11arMsgType;charch_Name「12]:charch_Msg【100」;}LOGINes1NFO:客户端与服务器端必须用相同的结构体LOGNIINFO来定义登录消息。否则,服务器端处理该消息时就会因不能识别而出错。(2)消息的定义结构体的第一个成员变量是消息的类型,整条消息在内存中存放在一快连续的存储空间中。通过解析消息第一位的内容来判断消息的类型。例如:eharMsgType=*(e--hTempBueff+r0)。(3)消息的处理流程当服务器端AccPet()接受到新的客户端连接时,为每一个客户端创建一个Socket指针对象,然后通过OnRecevie将客户端发送的消息存放到该实例的消息缓冲区中。当)、认j月程序空闲时,就会执行onldle()函数。山丁」本模块采用的是异步的非阻塞方式,所以消息的执行过程全部放到主线程中执行。这个时候就自定义了一个主线程的消息缓冲队列。重载onldze()函数,调用GetMe ageFro耐layersoeket()函数将每一个客户端实例对象的消息缓冲区中的消息和该实例的Socket指针存放到自定义的主线程的消息缓冲队列中。然后调用HandleMe ageBueffr()处理消息缓冲。东北大学硕士学位论文第三章消息处理与更新系统的设计与实现消息处理过程如图3.4所示:刃一:C}]en扒…严夔i…~…ICo eeto:匕。ZSend:oirtl扭d__l_…!曰二一)甲}】1SSS甲vrerrr厂下一少补e一1】}}图34消息处理过程Fig.3.4Poree ingMe age3,2自动更新系统网络游戏的一个重要组成部分是它的自动更新系统。正是由于程序内容不断更新,才使得网游的可持续性较强。同时这个系统也方便了开发人员做更新和维护。自动更新的原理就是为客户端的每个文件建立版本,服务器上拥有客户端的最新版本,客户端连接上服务器以后,获取关于文件最新版本的数据,并和本地版本对比,发现不同后服务器就把最新的文件传送到客户端,并更新版本号。自动更新系统的处理流程如图3.5所示:东北大学硕士学位论文第三章消息处理与更新系统的设计与实现{」一卜:C1ien协.}Create一一llllllllllfffffffffCo eeto甲}片罗鹦影鹦票午一一、日粉翌臀臀瞥鹦卜一.一~一图3.5自动更新系统的处理流程Fig.3.5proee FlowofTheAutomatielyUpdateSystem要发送文件还需要对指定游戏客户端目录里的文件进行版本维护管理。具体做法是:遍历目录下所有文件,然后进行压缩并产生一个版本信息的记录文件。自动更新系统模块由三个子模块组成:文件版本管理模块、文件传输服务器模块和客户端接受文件传输模块。3.2.1文件版本管理模块文件版本管理模块,通过对指定目录里的文件进行版本维护管理,递归地遍历整个目录和其子目录中的所有文件,并产生一个信息列表,同时压缩目录里的所有文件到指定目录。3.2.1.1文件版本管理模块的设计实现文件版本的管理首先需要建立文件的版本,标识一个文件的版本可以有很多方法:如手工为文件建立版本号或者利用文件的最后修改日期等。但是如果手工去产生文东北大学硕士学位论文第三章消息处理与更新系统的设计与实现件版本信息,那么文件数量巨大,很难人工维护而且容易出错。如果依靠文件的最后修改日期也不能总是保证正确,因为老文件替代出错的新文件或操作系统的时间改变都会影响修改日期。本文采用的是MDS信息摘要算法。MDS信息摘要算法全称是Me gae一DigesAtlgorihtms,它的主要作用是把一段数据摘要为一个128位长的数字,而这个数字可以唯一标识出这段数据。MDS可以把整个文件当作一个大文本信息,通过算法转换,产生唯一的MDS信息摘要。以后传播这个文件的过程中,无论文件的内容发生了任何形式的改变,只要重新计算这个文件的MDS值,就会发现是不同的,由此可以确定文件发生了变化。MDS的算法不需要支付任何版权费用,它包括4个文件glboal.h,mds.h,mdsc.c,mddrive.c。本模块利用这几个文件来建立文件的版本。本模块的接口函数设计如下:表3.3文件版本管理模块接口函数设计Table3.3APIofTheDocumentEditionManagementModule函函数原型型函数功能能CCCFileVersionMgr()))设置文件信息列表里所有文件的操作标志志为为为无效CCCheekl)irFile(ehar*Dir,intnFlag)))遍历指定目录所有文件,按Fnlga执行特定操操作作作作AAAddFilelnof(char*FileName,char*MDS,inttt添加单个文件信息到列表表 ize) UUUPdateFIlelnof(ehar*FilNeame,ehar*MDS,,更新己有的单个文件信息息IIInt ize)))))DDDataZTxt(ehar*FileName)))文件信息数据存盘(存成文本文件)))CCCheeDkiFrile(ehar*Di几intnFlag)))递归一个目录里所有文件(包含)子目录录CCCreateFileVersionlnof(ehar*Di,rintnFlag)))对指定目录创建版本信息息LLLoadVersionFile(veetorSFILE一INFO从文件里读取版本信息息***PFileList,maP< tring,int*PFIIelXd,,,ccchar*PszWOrkingDir,ehar*PszFileName)东北大学硕士学位论文第三章消息处理与更新系统的设计与实现
为了您的安全,请只打开来源可靠的网址 来自:
第一分享:
2011-05-31 12:43
本贴分享:
累计分享:
人发表观点
...目前还没有互动观点,输入您的互动观点
2006-2011 copy Baidu排序方式: 找到
相关内容约 63 篇,用时 0.001 秒 (
南方暴雨,处处遭灾,6月18日武汉市区平均积水50厘米,看看武汉人民的乐观精神,才知道啥叫真正的笑傲江湖~...
http:// .it.com.cn/viewthread.php?tid=644024&extra=page%3D1 age=1 -
2011-06-22 (
最近论坛上下都在讨论小月月的身世之谜,对此,我深感无奈,其实小月月的存不存在已经不重要了,重要的是我...
http:// .it.com.cn/viewthread.php?tid=570996&extra=page%3D1 age=1 -
2010-10-13 (
《凤舞天骄》7.20公测永久免费,激活码7月17日更新
最美的2D网游《凤舞天骄》终级内测不删档。并于7月20日