网页功能: 加入收藏 设为首页 网站搜索  
DirectPlay SDK中文翻译Understanding DirectPlay(1)
发表日期:2006-08-23作者:[转贴] 出处:  

Understanding DirectPlay(1)
作者:杨冰(源代码之光)
E-mail:iceryeah2000@163.com
创建时间:2002-9-26
最后修改时间:2002-10-6
备注:在Understanding DirectPlay章节中包括许多技术细节,为了达到清晰的翻译,有些句子我没有直接按原文翻译。而是经过自己的理解,润色,意译而成,有些句子更像一般教程里的话。另外,我没有翻译其中的Peer-to-Peer Sessions和Understanding DirectPlay Voice,因为,大家用这两部分的技术很少,并且技术还是相对简单的。

目录:
  Client/Server Sessions
  Initiating a Client/Server Session
  Selecting a Service Provider for a Client
  Selecting a Client/Server Host
  Connecting to a Client/Server Session
  Managing a Client/Server Session
  Normal Client/Server Game Play
  Terminating a Client/Server Session

正文:

Understanding DirectPlay(1)
(这里是Understanding DirectPlay第一部分,翻译的是Client/Server Sessions章节。)

这部分讲述DirectPlay背景知识。使你理解如何在游戏中使用DirectPlay API。

Client/Server Sessions
客户/服务会话由一组角色(Player,我把它翻译成角色,是因为一个用户账号可以对应多个角色),或一组客户端,连接中央服务器而成。DirectPlay有一个麻烦的事情:在客户/服务模式下,一个客户端不知道另外其它客户端的状态,只有服务器知道。当消息需要在两个单独的客户端之间传送消息,麻烦就出现了,因为DirectPlay没有提供直接客户对客户这样的消息传送方式。所以需要客户/服务会话来解决。

一个客户/服务会话分为两个部分:
1 服务端程序运行在远程电脑上。服务器的基本功能是一个中央消息轮,以及游戏主机。服务器必须接收和管理所有从客户端发送的消息,并且发送处理后的消息以进行恰当的回应。任何从一个客户端传送到另一个客户端的数据,都必须依靠服务器进行传送。
2 一个客户端程序,它运行在玩家的电脑上。此程序最主要的功能是管理UI(用户界面),并且保持游戏状态和服务器同步。

有某些部分只是被其中一个部分所负责。比如,玩家的图形引擎必须要由客户端程序完成。不过,处理过程的大多数方面,都需要两方面共同完成。编写一个高效的客户/服务类型游戏需要注意如何对客户/服务这两部分进行分工。

这部分文档描述客户/服务游戏的基本原理:

Initiating a Client/Server Session
一个客户/服务游戏能通过大厅进行连接,或者直接的通过服务端进行连接。

服务端程序
客户/服务游戏通常被大厅安排进程。连接服务端程序由两种方法,第一种方法(建议使用)就是使游戏拥有支持大厅功能,这样就可以直接连接到服务端。这种方法的优点是能让服务端和大厅可以在一个会话中进行通讯。
服务端也可以直接被客户端连接,自己进行广播,等待客户端加入。这部分在Selecting a Client/Server Host(选择一个客户/服务主机)有细节描述。

当服务端程序被运行,它必须调用IDirectPlay8Server::Initialize进行初始化。和DirectPlay其它初始化函数一样,这个函数的主要目的是提供一个DirectPlay指针,指向回调消息句柄(callback message handler)。然后调用IDirectPlay8Server::SetServerInfo描述当前游戏。客户端直到这个函数被调用才能够连接服务端。

客户端程序
首先你必须决定你的游戏是否是在大厅里进行和服务端连接的。如果是那样的话,创建和初始化一个支持大厅程序对象(CLSID_DirectPlay8LobbiedApplication)。这样,你就可以通过对象指针来指向你的消息。消息处理机从支持大厅程序的对象处接收消息,也就是间接的接收大厅客户端和大厅的消息。

1 如果是支持大厅连接的话,IDirectPlay8LobbiedApplication::Initialize返回一个连接大厅客户端的句柄,并且DPL_MSGID_CONNECT消息从支持大厅程序消息处理器发送。PdplConnectionSettings连接的结构指针指向DPL_CONNECTION_SETTINGS结构,这个结构里面包含地址对象。
2 如果程序不是通过大厅进行连接,则你既不接收连接句柄,也不接收消息。不过,如果你调用IDirectPlay8LobbiedApplication::SetAppAvailable,一个大厅客户端会稍后连接你的运行程序到一个会话中,并发送DPL_MSGID_CONNECT消息。

你应该创建和初始化一个客户对象(CLSID_DirectPlay8Client)。这个对象是你进行通讯的主要工具。如果你想有一个多人角色在会话中,你必须为每一个角色创建一个独立的实例对象给它们。

Selecting a Service Provider for a Client
所谓的服务提供就是你的网络连接协议。大多数游戏使用TCP/IP或者Modem协议,不过DirectPlay还提供了serial和IPX两种支持。
如果你的用户用大厅客户端联入了一个会话,你可以通过检验DPL_CONNECTION_SETTINGS来决定所要使用的网络协议,即服务提供,这个结构是伴随DPL_MSGID_CONNECT消息的。你或者可以询问用户来决定使用什么样的协议。通过客户对象中的IDirectPlay8Client::EnumServiceProviders函数来枚举当前可用的网络协议。在Using DirectPlay Enumerations有详细介绍。
一旦你选择了一个协议,你要创建一个DirectPlay地址对象给你的用户(一个设备地址)。你可以用这个地址通过一系列的数字(从DirectPlay函数中获得)来定义你的设备。在DirectPlay Addressing有详细对DirectPlay地址和地址对象的讨论。

Selecting a Client/Server Host
根据定义,服务端程序主持会话。要加入到会话中,客户端程序必须获得服务器主机的地址。通用的检取主机的方法是通过大厅服务器。这样,当一个用户连接到会话,你接收到的连接信息DPL_MSGID_CONNECT将包括主机的地址。结构中pdp8HostAddress成员有指向主机地址的指针。
如果服务端使用IP/IPX网络协议,也可以创建一个广播会话(broadcast session),在局域网中。创建广播会话,可以调用IDirectPlay8Server::SetServerInfo。然后调用IDirectPlay8Server::Host来发布主持会话的主机。你可以通过IDirectPlay8Server::Host函数的pdnAppDesc 参数更改DPN_APPLICATION_DESC结构,以获得更详细的配置信息。

你可以让你的用户查找可用的主机或者会话。可以在客户端程序上使用IDirectPlay8Client::EnumHosts来获得此项功能。一旦用户选择了一个主机,你就可以请求连接了。

Connecting to a Client/Server Session
所有的客户端必须加入所联入主机的会话中,即使这个会话是通过大厅来管理的(当客户联入主机中,就必须联入会话,否则,服务器就曝光了:)杨冰注)。一个连接把客户端看成一个会话成员,并且提供主机与客户端联系的信息。主机有权同意或否决接收一个连接请求。
服务端程序

当一个客户端试图加入一个会话,主机接收到DPN_MSGID_INDICATE_CONNECT消息。如果同意此客户端加入,返回S_OK,不同意则返回其它任意值。客户端将接收DPN_MSGID_CONNECT_COMPLETE消息,这里包含服务端程序对它的回复。你可以在这个时候定义角色信息索引(player context value)(字面上,没有索引的意思,但它实际提供了一个索引功能。杨冰注),或者等到你接收到DPN_MSGID_CREATE_PLAYER消息。在Using Player Context Values章节中进一步的详细介绍。

如果角色成功的加入会话中,所有的客户端和服务端将接收到DPN_MSGID_CREATE_PLAYER消息以及角色ID(DPNID)。如果你想定义一个角色信息索引,并且现在还没有做,你在此消息回应前必须定义好,否则,你将不再拥有更改此项的权力。
客户端程序

为了连接到会话,你必须取得会话主机的地址。如果你的游戏是通过大厅客户端连接的,你可以通过IDirectPlay8LobbiedApplication::GetConnectionSettings.来获得主机的地址。
如果你没有会话主机的地址并且你使用IP或者IPX网络协议,你可以通过IDirectPlay8Client::EnumHosts在广播会话中寻找可用的主机。你可以通过枚举可用的主机来取得地址。DPN_APPLICATION_DESC描述关联的会话。

为了加入会话,调用IDirectPlay8Client::SetClientInfo来设定角色名称(name),然后调用IDirectPlay8Client::Connect以及获得得主机地址来连接会话。
你将会接收到DPN_MSGID_CONNECT_COMPLETE消息回应。如果主机同意这次连接,hResultCode成员会被设置为S_OK。如果不是,hResultCode将被设定为DPNERR_HOSTREJECTEDCONNECTION。

Managing a Client/Server Session
作为主机,服务端负责管理会话。它含有以下几个基本工作方面:
1 管理会话成员列表和他们的网络地址。DirectPlay已经做好了这个任务,但是服务端程序还要提供管理用户数据的功能。
2 判断一个新用户是否可以加入到会话中。
3 为新用户提供当前的游戏状态。

当一个用户试图加入会话,主机将接收到DPN_MSGID_INDICATE_CONNECT消息。如果接收这个用户,则返回S_OK。返回其它值则表示不同意。用户则接收消息DPN_MSGID_CONNECT_COMPLETE,其中包含主机发送给它的返回值(S_OK或者其他)。
主机可以调用IDirectPlay8Server::DestroyClient.把用户移出会话。

Normal Client/Server Game Play
在DirectPlay中,消息本质上是一些从客户端发送到服务器或连接程序(vice versa,通过提供的功能翻译)的游戏数据。DirectPlay没有具体的规定这些数据块的结构或内容,它只是仅仅提供了传递机制。一旦游戏开始运行,每个客户端将从服务端或连接程序接收有关游戏的消息数据流。这些消息的传递,就是为了让各个客户端状态达到同步,以便每个用户都看到相同的UI(用户界面)。

对于大多数游戏,尤其是那些状态更新迅速的游戏,你要更加小心的管理你的消息。DirectPlay消息发送级别管理装制(throttles outgoing messages)可以依据发送的消息级别而管理发送各个消息的先后顺序。现在你只要依据各个消息的主要性,来安排发送级别就行了。在Basic Networking章节中有详细讨论。(此段多为意译。冰注)

服务端程序:
调用IDirectPlay8Server::SendTo,发送消息给客户端。然后客户端会接收到消息DPN_MSGID_RECEIVE。

客户端程序
调用IDirectPlay8Client::Send,发送消息给服务端。服务端将会接收到DPN_MSGID_RECEIVE消息。

备注:DirectPlay没有提供客户端之间进行通讯的机制。任何客户端之间要进行通讯,必须要通过服务端程序。

使用组(Groups)
很多游戏允许角色加入一个组里。比如,一个以班(squad-based)或者说是分组的游戏,每个角色都是一个组成员。DirectPlay允许服务端为角色创建组。如果你的游戏里设定的组与DirectPlay提供的组差不多,完全可以使用DirectPlay为你提供的设置。DirectPlay组在本质上是为了简化消息管理。当你定义了一个组,你就可以用一条IDirectPlay8Server::SendTo来给组里的每个角色发送消息。

调用IDirectPlay8Server::CreateGroup.来创建一个组。你的消息管理器随后回接收到DPN_MSGID_CREATE_GROUP消息。这个消息其中包括组的ID(用来作为发送的识标)。一旦组建立起来,你就可以用IDirectPlay8Server::AddPlayerToGroup.来添加角色。

当你的组完全建立好后(角色已经被加入等),你就可以调用IDirectPlay8Server::SendTo来给组发送消息,其中dpnid参数被设为组的ID。所有的组成员将会接收到消息DPN_MSGID_RECEIVE。
可以调用IDirectPlay8Server::RemovePlayerFromGroup.来移除角色。最后,销毁组调用IDirectPlay8Server::DestroyGroup。

Leaving a Client/Server Session
客户端可以调用IDirectPlay8Client::Close.来离开会话。服务器将被消息DPN_MSGID_DESTROY_PLAYER通知。

Terminating a Client/Server Session
要结束一个客户/服务模式会话,服务端调用IDirectPlay8Server::Close。如果没有其他主机接管,则将结束所有连接的会话。客户端将接收到DPN_MSGID_TERMINATE_SESSION消息.
服务端然后将接收DPN_MSGID_DESTROY_PLAYER消息从每位玩家,包括它自己。IDirectPlay8Server::Close是同步的,直到所有返回的DPN_MSGID_DESTROY_PLAYER消息都被处理才返回。当IDirectPlay8Server::Close被返回,就可以安全的关闭服务端程序。
 

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 DirectPlay SDK中文翻译Understanding DirectPlay(1)
本类热点文章
  udp服务器设计过程总结
  理解I/O Completion Port
  Internet 即时通信系统的设计与实现
  Epoll为我们带来什么
  Winsock开发网络通信程序的经典入门
  DirectPlay SDK中文翻译Understanding ..
  DirectPlay SDK中文翻译--Introduction..
  DirectPlay SDK中文翻译Understanding ..
  Winsock 函数简介
  DirectPlay SDK中文翻译Understanding ..
  Winsock程序设计初步之 Winsock编程原理
  非阻塞 Socoket 编程
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00428