DirectX简介 第四篇 DirectPlay简介

DirectPlay简介

1.       DirectPlay允许开发者提供不考虑传输媒介细节特征的多人参与功能,DirectX对不同的媒介同等对待(无论是TCP/IP网,IPX网或是调制解调器)

2.       DirectPlay对象

DirectPlay:提供DirectPlay的核心功能,它的接口给管理游戏者、组、游戏会话和数据传送提供各种方法。

DirectPlayLobby:为DirectPlay游戏提供场所空间,与实际的大厅一样,游戏者在这里见面并互相作用,此对象为启动和跟踪DirectPlay会话提供方法

3.       结构:DirectPlay主要目的和DirectX其他部件一样,都是提供展示硬件功能的一致接口

服务提供器:为开发者提供一致的接口、隐藏了通信协议间的差别、允许第三方开发者编制自己的服务提供器

最终解决方案的结构:游戏或其他应用程序与管理着一组服务提供器的DirectPlay交换信息,这些服务提供器中有思想DirectPlay连在一起:网络IPX/SPX、网络TCP/IP,调制解调器以及串行连接,网络服务器以Winsock作为基础,调制解调器以WindowsTAPI作为基础

4.       DirectPlay游戏

(1)       基于所有的服务提供器,程序可以同时拥有在同一传输媒介上运行的不同游戏的多个不同会话,DirectPlay为列举会话,创建新会话以及与现存会话相连提供多种方法,另外也可以用密码对会话进行保护,这时要求对用户的鉴定,会话被创建后,游戏就可以与之相连.DirectPlay提供了创建、删除、列举、描述游戏者的方法,游戏者也可结成小组以使管理更加容易,通信效果得以改进。

(2)       通信:DirectPlay在游戏者间既可以共享数据也可使用消息机制来传递消息。传送的数据可以被加密或用数字签名,DirectPlay还产生系统消息,可由此获知会话的状态

DirectPlay通讯机构是对等的客户/服务器式的兼而有之。

对等结构:对于网络服务提供器而言,每一新连入的DirectPlay对象在与会话主连接时都会收到一份其他DirectPlay对象的列表清单,这一表单在会话之中始终被保留着,每一DirectPlay对象都知道其它的对象,所以它们直接进行消息传送而不用通过会话主,所得到的会话也是对等的

客户/服务器结构:每一条消息都必须传给会话主

5.       应用程序设计

设计多人参与的应用程序需解决的最重要问题是同步问题

输入同步:一个游戏者的输入也输到其他游戏者那里,并当成同一机器具有多个输入设备处理(易于理解、易于实现、没有有效利用带宽、不健全)

状态同步:由本会话将状态传给其他会话

6.       DirectPlay标签项

 

使用DirectPlay

7.       DirectPlay的设置要求比其它的大部分DirectX部件困难得多

8.       GUID知识(全局唯一标识)

(1)       GUIDCOM结合使用,来识别对象和接口,并在需要有独特的标识符时出现

(2)       创建GUID(用于创建GUID的短小命令行程序称为UUIDGEN,这在许多编译器中都有)

9.       DirectPlay传送数据前的一些预备步骤

(1)       创建DirectPlay对象

(2)       列举连接快捷方式

(3)       让用户选择一种快捷方式

(4)      应用选择的快捷方式完成对DirectPlay对象的初始化

(5)       列举所有已存在的通讯会话

(6)       打开一个已存在的会话,或新创建一个

10.   DirectPlay对象

(1)       创建DirectPlay对象是建立一个通用的、与媒介无关的信道的第一步,尽管DirectPlay支持DirectPlayCreate功能,但它已过时。对DirectPlay而言,创建DirectPlay对象时推荐使用CoCreateInstance方法

DirectPlay对象与其它DirectX对象不同,在CoCreateInstance后并不是马上调用初始化方法。事实上,DirectPlay对象没有初始化方法——而是用InitializeConnection方法最终初始化DirectPlay对象,但首先要做其它工作

(2)       ANSIUNICODE

创建DirectPlay对象时,可以选择建立采用标准的ANSI 8位字符集的接口,也可建立采用DirectPlay字符集处理字串的接口,Unicode是用16位字符表示字串的国际标准

11.   取得连接

(1)       服务提供器:是应用DirectPlay时用到的最底层的机能,它结合了HALHEL的机能

(2)       连接快捷方式:把服务提供器封装起来的一种抽象概念,一个连接快捷方式封装了建立特定通讯信道所需的信息,这一信道可支持一个DirectPlay通讯会话

连接快捷方式是有标记的——它提供了在用户面展示程序名或通讯服务的机会

(3)       列举连接

多数情况下,创建DirectPlay对象后要做的第一件事是给用户提供一份现存的连接快捷方式列表,并允许用户进行选择(EnumConnections方法)

(4)       初始化连接

InitializeConnection方法把指定的服务提供器绑定DirectPlay对象,同时也在提供的连接缓冲区中搜索可被服务提供器用来建立信道的信息块,为稍后使用这些块,要对它进行剖析后再存储

建立DirectPlay会话所需要的最终数据总量随选择的连接快捷方式不同而不同

12.   会话管理

(1)       一个DirectPlay会话是一个多人游戏或其它DirectPlay应用程序的单一实例

(2)       会话说明

成功地运用多数会话管理方法的诀窍在于适当地填充传给所用方法的DPSESSIONDESC2结构

(3)       列举会话:EmumSessions(同步列举(等待)和异步列举)——回调函数

GUID_NULL(不是NULL)定义为具有0值的GUID

(4)       打开会话:Open方法(程序GUID和会话GUID

受保护的会话:密码保护和私有会话

转移会话:创建会话时DPSESSION_MIGRATEHOST标志

(5)       关闭会话:Close方法

 

消息处理

13.   DirectPlay通讯(DirectPlay对象间交换信息):

(1)       定制消息:应用程序执行大多数通讯工作时都是由用户定义的定制消息

(2)       系统消息:告知会话成员会话的状态和运行情况等

系统消息:DPSYS_为前缀

定义消息:DPMSG_为前缀

(3)       共享数据区:当改变共享数据区的数据时,所做的改变将自动地在会话中的DirectPlay对象间传递(传递所作的改变仍然要用到消息,只是DirectPlay内部处理了这些消息)

14.   对游戏者的管理(DNAME

(1)       游戏者是指DirectPlay会话的参与者,游戏者是消息传送路线的起始和终止点

(2)       管理游戏者:CreatePlayer(创建一名游戏者)、DestroyPlayer(注销一名游戏者)、EmumPlayer(列举游戏者)、SetPlayerName()、GetPlayerName(获取游戏者DPNAME结构)、AddPlayerToGroup(向游戏小组中增加一名游戏者)、DeletePlayerFromGrop()、SetPlayerData(设置游戏者的本地或共享内存区)、GetPlayerData()

(3)       标识游戏者:由PlayerPlay ID标识,此值在会话中是唯一的

(4)       管理小组:CreateGroup(创建新的最高级别的小组)、CreateGroupInGroup(创建包含在另一个小组内的子小组)、AddPlayerToGroup()、AddGroupToGroup(将一个小组加入某小组)、DestroyGroup()、EnumGroups()、GetGroupName()

(5)       标识小组:与标识游戏者同样的方法idGroup

(6)       小组和带宽

使用DirectPlay小组来组织每个队,不仅可以保存使用者的有关记录,也可以帮组DirectPlay获取更多可用的通讯能力

群组优化(节省带宽等)

15.   DirectPlay消息运作(靠消息序列进行相互之间的通讯)

(1)       消息的完整性(接到一条消息后,确认传输过程中没传错,才能放入消息队列)

(2)       发送消息

Send方法:把消息发给单个的游戏者、一群游戏者或整个会话(发送消息时没有消息队列,所以Send方法结束后,消息就已被传到通讯媒介上了)

(3)       接受消息

Receive方法:从消息队列中取出消息(缺省操作是移出消息队列中下一条消息)

          接受缓冲区的大小(不适合用固定缓冲区):提供全局的通讯缓冲区,若大小不够,调整缓冲区的大小(缓冲区太小时,Receive方法将返回DPERR_BUFFERTOOSMALL错误)

          抽取消息:尽管DirectX部件能够用于多线程的应用程序,但并不推荐这样使用,对消息队列的处理能给完美的程序提供单独的线程——一个监视消息队列并把消息抽取到程序的线程。事实上,用任何其他方法进行处理都是对资源的浪费

                   当游戏者接收到消息时,使用CreatePlayer方法提供的事件句柄参数指定要被触发的事件更有效

                   Windows API函数WaitForMultipleObjects方法等待事件对象

           破解消息:DPMSG_GENERIC消息结构(dwType:系统消息标识)

(4)       定制的消息

(5)       处理系统消息(加入到会话中的Directplay对象通过系统消息使程序获知会话的进程和状态)

当游戏者或小组添加到会话中时,DPSYS_CREATEPLAYERORGROUP消息会传给会话中的游戏者;当有游戏者或小组被注销使,DPSYS_DESTROYPLAYERORGROUP消息将传给会话中的游戏者;DPSYS_HOST,会话主转移到新的Directplay对象

(6)       监视通讯进程

消息交换中引入的延迟称之为latency

服务器提供的时延(GetPlayerCaps返回的DPCAPS结构)、帧动画率

(7)       共享数据区:Directplay允许将特殊的数据区与游戏者或小组关联,这些数据区相对于创建它们的DirectPlay对象来说可以是本地的,也可以是远程的,远程数据区自动在会话中传递,允许给其他游戏者发送数据而不用显示的进行消息发送,只有创建游戏者或小组的DirectPlay对象才能改变它的关联数据区(只有特定类型的数据适合于这种特定的数据区(指针、句柄不适合),改变速度快的数据也不宜用于远程共享,不常改变的数据才适宜用于共享数据,否则用消息)

(8)       设置数据:SetPlayerDataSetGroupData方法设置数据区中的数据(只有创建游戏者或小组的DirectPlay对象才能改变相关的数据区)

(9)       取得数据:GetPlayerDataGetGroupData方法

(10)   远程数据消息:远程数据区域更新后,DirectPlay给会话中的每一个参与者都发送一条DPSYS_SETPLAYERORGROUP消息,用户程序根据需要做出响应

(11)   本地数据区:此数据区和远程数据区一样关联到小组或游戏者,但并不在DirectPlay对象间传递,这是提供给开发者的一种方便功能,它可以保存一点薄记内容,同时它也使管理多线程程序中的数据变得更容易,因为DirectPlay能确保同一时间只有一个线程访问此数据区

(12)   数据区完整性

16.   会话说明

(1)       SetSessionDesc方法可以改变会话说明(使用会话说明作为共享数据区并不非常好,因为只有会话主可以改变此说明,还有,由于会话说明是用共享数据功能传递的,它也受相同的限制,而且不能使用快速变化的数据)

(2)       对此功能的一种可行的使用是让会话主定期用游戏中的比分,等级以及其他让准备加入此会话的人感兴趣的数据更新一块用户区,此信息在浏览会话者列举有效会话时传递出去,另一可行的用法是用于要求与会话连接的用户具有特定的等级映射,所需映射的标识存在于会话说明中,用于滤出有效的会话

17.   应动态分配接收缓冲区,否则可能使程序不能与后续版本的DirectPlay兼容

18.   共享数据区不要用于快速变化的数据

           

大厅

19.   大厅服务器、大厅客户、应用程序

20.   DirectPlayLobby对象:提供程序用来处理大厅接口的方法

21.   能用于大厅的程序(可以直接启动,也可以由大厅启动)

(1)       将程序注册为能用于大厅的

(2)       在程序初始化期间创建一个DirectPlayLobby对象并检测连接参数

(3)       如果有提供的参数则使用它,否则以单独模式继续

     注册程序:EnumLocalApplication方法获取安装于用户机器上与之兼容的应用程序列表

               使程序能用于大厅的第一步是使之出现在这张表上:DirectXRegisterApplication函数(作为程序安装过程的一部分而被调用),该函数需要一个DIRECTXREGISTERAPP结构,此结构中含有DirectPlay和大厅客户启动程序时需要的全部信息

查找大厅

应用程序初始化时需要检测它是运行于常规方式(双击图标)还是由一个大厅启动的,如果程序是由大厅客户使用RunApplication方法启动的,则连接信息通过一块特殊的程序间的通讯区传给此程序,程序可以通过创建自己的DirectPlayLobby对象并尝试取出连接设置来访问这一区域,DirectPlayLobby对象可以用DirectPlayLobbyCreate函数创建,也可以由CoCreateInstance以前面熟悉的方法创建

DirectPlayLobby对象创建成功以后,就可以使用它的GetConnectionSettings方法检测连接参数了

程序使用Connect方法完成大厅启动步骤

DirectPlay用一种特殊的系统消息序列把由大厅客户调用RunApplication而启动的程序状态通知给客户

22.   自带大厅

(1)       DirectPlayLobby除了把游戏者聚集在一起外,另一种十分有用的功能是免除用户为会话提供连接参数的“义务”,自带大厅的应用程序创建自己的大厅,填充自己的连接结构然后打开一个会话,如果连接结构提供了全部必要的信息,服务器提供器将不再要求输入或显示状态消息

(2)       DirectPlay地址:DirectPlay把与会话连接所需要的信息封装到一个DirectPlay地址中,DirectPlay地址由一个或多个数据块组成,它们共同定义了完整的地址,这些数据块由GUID来标识。

(3)       初始化连接:DirectPlay对象的InitializeConnection方法

(4)       列举会话:EnumSessions方法

 

应用DirectPlay

23.   同步

(1)       等待时间

(2)       刻板的(慢速、精确)和灵活的(快动、不精确)

(3)       设计时的考虑

1.       正在进行什么(基本因素和事件(确定、不确定和随机三种))

2.       谁是主管

3.       管理

24.   刻板的同步技术可用于轮流进行的游戏,但它会使动作迅速的动作游戏停顿下来,也易于丢失消息。

25.   尽量避免传递那些可从游戏实例获得的数据

26.   设计出的消息序列应能容忍偶尔地消息丢失

27.   有保证的消息发送占用大量的开销,应该在绝对需要的时候再使用

你可能感兴趣的:(DirectX简介,游戏,通讯,服务器,多线程,网络,windows)