【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 4035|回复: 6

[DirectX] DirectPlay SDK中文翻译--Introduction To DirectPlay

[复制链接]
发表于 2005-12-29 13:39:50 | 显示全部楼层 |阅读模式
Introduction To DirectPlay
翻译:杨冰(源代码之光)
E-Mail:iceryeah2000@163.com
创建时间:2002-9-11
最后修改时间:2002-10-1
备注:此章节是在翻译完Using DirectPlay章节后翻译的,对很多术语的翻译都经过了很长时间的考虑,可能还有不妥之处,会在以后更正。

目录:
  
Creating and Managing Sessions
  DirectPlay Network Communication
  DirectPlay Transport Protocol
  Communicating with DirectPlay Objects
  DirectPlay Lobby Support
  
正文:

Microsoft? DirectPlay? API为开发者提供了开发诸如多人游戏或聊天程序的工具。一个多人游戏有两个基本特性:
1 两个或更多的独立用户,每个用户都拥有客户端游戏程序
2 网络连接了用户的电脑(通过中央电脑服务器连接)
DirectPlay提供了一个额外的层,使你的游戏和网络底层相隔。并且,你的游戏可以非常简单的使用DirectPlay API,并使用DirectPlay管理网络通讯。DirectPlay提供的特性,使多人游戏在开发中得到了很多简化。其中包括:
1 创建和管理点对点,客户/服务会话(Session)
2 在一个会话中管理用户(User)和组(Group)
3 管理在不同网络平台上进行会话的成员之间发送的消息
4 使游戏在大厅(Lobby)中互动
5 使用户可以进行语音互动

  这部分的文档(Introduction To DirectPlay)高度概括了DirectPlay的功能。随后的章节将告诉你DirectPlay的细节和如何在你的游戏中使用DirectPlay。

Creating and Managing Sessions
  游戏会话是一个特殊的多人游戏。会话中会有两个或者更多的用户同时在线,用户彼此拥有相同的游戏客户端。角色(Player)在游戏中是一个实体,它被游戏所定制。每个用户可以拥有多个角色。不过,游戏必须自己管理这些角色,使用DirectPlay接口对象来管理这些角色。

创建会话的第一步就是收集一组用户的信息。有两种方式:
1 大多数游戏会话都被一个运行在远程计算机上大厅程序(lobby application)所管理。大多数基于Internet的游戏都用这种方式。
2 各个用户自己相互进行联系。这种方式一般用在小型的局域网中。并且游戏不是很大。

会话被管理后,游戏就可以被连接。在会话过程中,角色可能从会话中退出,或者新的角色被加入。

  在多人游戏中,同一会话中的用户UI应该进行同步。管理多人游戏会话应该反复发送消息流给每个用户。比如,每当角色移动,一个消息就应该被发送,以便在所有其他游戏客户端更新角色的位置。DirectPlay的核心就是为所有在一个会话中的计算机发送高效安全的消息。

有两种基本方式来组织会话消息,一种是点对点,一种是客户/服务模式。讲这两种模式的资料很多,这里就不再复述。

DirectPlay Network Communication
   DirectPlay的主要功能是使游戏和网络底层分开。如果你需要发送状态更新的消息,你可以很简单的调用DirectPlay API,不必在意复杂的网络连接情况。DirectPlay网络服务提供了多种网络连接支持:TCP/IP, IPX, modem, 和 serial links。

DirectPlay Transport Protocol
   DirectPlay网络核心是DirectPlay协议。这个传输层协议在DirectPlay8中完全重写,现在已经被用在所有的消息中。DirectPlay协议重点放在让你可以很简单的发送消息。协议为多人游戏提供了很多量身定制的特性,包括:
1 可靠和不可靠的消息传递。可靠传递的消息是不断的发送,直到目标程序确信接收了他们。你可以根据你的情况分配消息的具体发送方法。
2 连续和非连续消息传递。连续消息被一个个传送到目标程序中。
3 消息分割和打包。当消息的大小超过网络的许可,DirectPlay将自动进行分割和重组打包。
4 阻塞控制。DirectPlay会自动控制(throttles)你传出消息的速度,使目标程序能够执行和接收消息。
5 发送顺序。要确保重要的消息被首先发送,DirectPlay可以设置消息的发送级别,其中包括low, medium, 和 high priority。High priority(最高优先发送)消息被最先送上消息队列的前端,然后是medium和low。
6 消息超时处理。防止消息队列被阻塞,DirectPlay允许你分派每个消息一个超时值,当这个消息超时后,便从消息队列中移除。 DirectPlay Addresses

为了传送消息,每个加入多人游戏的人都要有一个唯一的地址。运行游戏客户端的电脑提供设备地址,而游戏主机将提供主机地址。

DirectPlay的地址是一个URL字符串。这些字符串由如下格式构成:
x-directplay:/[data string]
在不同的网络连接上,它包含发送消息方和接收方这样的元素。
DirectPlay地址对象会生成URL字符串。依你的熟练程度,你可以直接使用URL地址或者通过DirectPlay地址对象来管理URL。(using the methods exposed by the address object to handle each element of the data string separately)

Communicating with DirectPlay Objects
   DirectPlay其实是基于COM的。各个组件管理各个不同的方面。比如,DirectPlay点(peer)对象(CLSID_DirectPlay8Peer),就是负责管理点对点游戏的。

你通过组件的接口来和它通讯。比如,在点对点游戏中,你发送给另外用户数据时,使用IDirectPlay8Peer::SendTo。DirectPlay会发送消息到目标。

DirectPlay通过很多callback functions(回调函数)进行联系。在原理上,这些函数和windows程序使用得回调函数一样。游戏执行这些callback function,在DirectPlay初始化期间传送函数指针。当DirectPlay需要通讯时,它调用callback function,并且传递两个重要信息:
1 鉴定消息类别ID。
2 一个数据块指针,一般是一个结构体。

比如,当一个消息发送上面的信息到目标,目标程序的callback function将接收到DPNMSGID_RECEIVE消息ID,指出那个消息已经到达。并伴随着包含数据的结构。

因为大多数的DirectPlay消息是多线程的,其中关键就是callback function如何被恰当的执行。

DirectPlay Lobby Support
  大厅(Lobby)主要的任务是安排角色会面和安排游戏。大厅服务器(Lobby servers)一般还有其他功能,比如主持聊天室,发送新闻和信息,主持商业买卖。大厅服务器可以便利的使用和安排多人游戏工作,但它不是必需的。多人游戏也可以直接在大厅客户端之间进行通讯(lobby clients)。

一个具有大厅的多人游戏,由三个部分组成:
1 大厅服务器
2 大厅客户端
3 支持大厅的游戏(A lobbyable game)

DirectPlay没有具体的告诉大厅服务器如何工作,你可以自己安排。DirectPlay提供了对大厅客户端的支持。一个大厅客户端通过大厅服务器连接程序(vendor)进行工作,连接程序被安装到用户的系统上。它就像一个链,来连接用户和大厅。当你要直接进行通讯,你必须知道每个大厅的工作细节。

大厅客户端游戏接收大厅服务器的通讯细节,使用恰当的通讯协议。大厅客户端进行用户和游戏程序之间的通讯。游戏也能使用接口传送消息给大厅客户端。

大厅实际可以连接任何程序。不过,游戏必须有某些具体的大厅支持组件(lobby-aware components)。一般的,一个支持大厅的游戏可以通过会话和大厅客户端进行联系。如果游戏被注册成支持大厅,大厅客户端能自动的接收更新信息,并在游戏里进行相应的更新。诸如host migration。
 
 楼主| 发表于 2005-12-29 13:40:16 | 显示全部楼层
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:estroyClient.把用户移出会话。

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:estroyGroup。

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被返回,就可以安全的关闭服务端程序。
 
 楼主| 发表于 2005-12-29 13:40:29 | 显示全部楼层
Understanding DirectPlay(2)
作者:杨冰(源代码之光)
E-mail:iceryeah2000@163.com
创建时间:2002-9-26
最后修改时间:2002-10-15
备注:被部分翻译的是DirectPlay Lobbies章节。主要讲述了DirectPlay的大厅机制。

目录:
  DirectPlay Lobbies
  DirectPlay Lobby Architecture
  Lobby Servers
  Lobby Clients
  Communicating with a Lobbyable Game
  Lobbyable Applications
  Launching a Lobbyable Application

正文:

DirectPlay Lobbies
大厅(lobby)的主要目的是安排用户使用多个网络游戏,这样的机制使不同类型的游戏集合在一起,有利于管理和用户选择。大厅程序通常运行在远程服务器上。用户访问大厅(可通过多种方式:通过互联网/局域网建立一个会话或加入一个会话都可以访问大厅)。大厅程序然后会连接运行(launch)组里的游戏,游戏这时就开始运行。
因为大多多人游戏都是拥有大厅的,基于DirectPlay的游戏一般都支持大厅程序。这部分就是讨论如何使DirectPlay游戏具有支持大厅的功能。

DirectPlay Lobby Architecture
安排和管理基于DirectPlay多人游戏会话的过程包括五个独立的组件。大厅服务端程序是第三方组件(通过互联网在远程服务器上运行)。其余的四个组件都被安装在用户计算机上。
1 大厅客户端(Lobby client)。大厅客户端是用来和大厅服务器(lobby server)进行联系通讯的。它主要是通过DirectPlay大厅客户端对象(lobby client object)和用户的游戏程序进行通讯。
2 支持大厅的游戏(Lobbyable game application)。它使用DirectPlay lobbied application object(大厅游戏程序对象)和大厅客户端进行通讯,然后再通过大厅客户端与大厅服务端进行联系。
3 DirectPlay大厅客户端对象(DirectPlay lobby client object)。
4大厅游戏程序对象(DirectPlay lobbied application object)(从lobbied被动式来讲,这是对游戏程序,表示该游戏支持大厅,可我找不到恰当精炼的语言来表达)
上面两个DirectPlay对象扮演了连接游戏程序和大厅客户端的角色。他们通过私有平台彼此进行联系。下面的图表示了关系和如何进行通讯联系的。(图片未复制,SDK有)

Lobby Servers
大厅服务器主要目的是安排角色和管理游戏。它一般建立在远程服务器上。大厅服务器通常还具有主持聊天,发送新闻,商品交易等功能。
要管理多人游戏,一个大厅服务器一般要做以下任务:
1 管理安排各个游戏会话和玩家的网络地址。
2 通过相应的游戏程序来连接相应的会话。
3 将角色加入现有的会话中。
4 保持会话中的电脑到正确的网络地址。
5 追踪会话的状态变化,诸如角色的离开或改变游戏主机。
具体的大厅服务器工作细节依具体的情况而定,但主要任务必须包括上述内容。

Lobby Clients
大厅客户端是负责与大厅服务端连接的程序,它被安装到每个玩家的电脑上。它负责玩家和他们的游戏程序,以及服务端之间的通讯。一个安装大厅客户端通用的方法是叫用户在游戏服务主页上进行下载。
大致的步骤如下:
1 新用户到网站上注册。
2 作为注册的一部分,客户端被下载到用户的电脑上。
3 用户决定玩哪个游戏,并进入该游戏会话。
4 网站开始连接用户电脑上的客户端程序。可以通过URL来指向一个客户端执行文件。
5 大厅客户端安排会话,并运行用户指定的游戏程序。
6 如果该游戏具有支持大厅功能,大厅客户端启用该游戏程序,让游戏程序直接和大厅服务端进行通讯。这个连接使大厅服务端保持追踪用户进入或者退出游戏的事件。
大厅客户端并不是必须和远程服务器进行连接。用户运行大厅客户端后,客户端会列出有效的游戏和会话。一旦用户选择了一个游戏和会话,大厅客户端则开始连接运行该游戏。
这部分讨论的是大厅客户端的一般知识。在Communicating with a Lobbyable Game.中会有对大厅客户端和其连接的大厅服务端更多的讨论。

Communicating with a Lobbyable Game
我们可以通过多种方便的方法让大厅客户端和与其相联接的大厅服务端进行通讯。DirectPlay在下面具体介绍了大厅客户端和支持大厅功能的游戏程序如何进行通讯。
大厅客户端不能直接的和游戏程序进行通讯。它是通过大厅客户端对象(CLSID_DirectPlay8LobbyClient)来和游戏程序通讯的。这个对象是从IDirectPlay8LobbyClient界面获得。如果游戏程序具有大厅功能,则此程序的客户端对象负责传递消息。用如下步骤使用IDirectPlay8LobbyClient对象。
1 在用户系统上枚举支持大厅的游戏。
2 连接游戏,如果此游戏没有运行,则连接它到会话中。
3 从会话中释放此游戏,并且关闭和大厅客户端的连接。
4发送消息给已经连接的游戏。
Note 大厅客户端可以运行任何程序,不管此程序是否具有支持大厅功能。不过,只有支持大厅的游戏程序才能使用DirectPlay去和大厅客户端进行通讯。
大厅客户端对象和大厅客户端进行通讯是通过回调函数进行的。函数指针在初始化期间被传递到大厅客户端对象。回调函数发送的消息如下:
1 连接信息。
2 连接状态。
3 会话状态,其中包括连接的,未被连接的和主持会话的主机。
4 从游戏程序发送到大厅客户端的消息。
运行(launch)一个程序
当你运行一个程序,你可以试图传递一个关于游戏具体情况的数据块给程序。当支持大厅的游戏被一个大厅客户端运行,则此游戏创建和初始化一个支持大厅程序对象(lobbied application object)。信息则通过此对象被传递到游戏。
当lobbied application object被初始化,则大厅客户端接收到消息来判断用户是否已经被连接。传递这个信息的主要目的就是为了让大厅客户端知道此游戏是否具有支持大厅功能。如果大厅客户端在运行此游戏的一段时间内,没有接收到这样的连接信息,则表示此游戏不具有支持大厅功能。你就可以停止这次连接。
运行程序后
此期间,大厅客户端和正在运行的支持大厅游戏相比没有作很多的工作。依靠游戏拓扑,大多的用户信息被直接发送到游戏服务器。不过,DirectPlay在发生断开连接和主机时,发送消息给大厅客户端。这些消息是为了让大厅客户端知道服务器当前的状态。比如,如果主机改变,大厅服务端会更新UI,指示新的主机。
游戏也能向大厅客户端传递消息。这些消息可以包括任何内容,它能被用于任何目的。大厅客户端一般传送数据给大厅服务端去处理。比如,在游戏的结束时,游戏可能会发送一段消息告诉大厅服务端,有新的分数纪录产生,请更新最高分列表。

Lobbyable Applications
具有大厅功能的程序(Lobbyable applications,翻译繁琐,以后直接引用英文)被设计直接和大厅客户端进行工作。当大厅客户端使用DirectPlay运行程序,Lobbyable applications在此时会显现出如下优点:
1 当游戏状态改变时,大厅客户端自动接收更新信息。
2 大厅客户端可以使用标准API来和游戏进行通讯。
3 游戏同时也能使用标准API来和大厅客户端进行通讯。
总之,DirectPlay实际上消除了游戏本身对网络通讯的硬编码。你可以在任何时候使用标准API或者基于其上,通过少量修改达到游戏的网络通讯要求。
在Launching a Lobbyable Application会有更多的关于lobbyable application的信息。
如果想知道lobbyable application具体的工作机理,查看Implementing a Lobbyable Application章节和SDK中SimplePeerhe和StagedPeer例子。

Launching a Lobbyable Application
当Lobbyable Application被运行后,首要做的是创建一个支持大厅功能程序对象。这个对象将赋予程序判断它是否真的被大厅运行。Lobbyable Application必须通过消息管理回调函数接收从大厅客户端发送的消息。从下列步骤来完成:
1 创建Lobbyable Application对象。
2 初始化该对象。
3 如果初始化返回一个有效值,则游戏被大厅连接运行。
4 检验在初始化阶段返回的用户的索引(context value)。这里包含着游戏的具体信息。
5 检验从lobbied application发送过来的连接消息。此消息中包括消息发送ID,依据此ID来给发送消息到大厅客户端。
当游戏成功的被大厅连接运行,DirectPlay就能自动的发送状态更新信息给大厅客户端。要开启自动状态更新机制,在IDirectPlay8Peer, IDirectPlay8Client, 或 IDirectPlay8Server接口中调用RegisterLobby。你也可以使用lobbied application接口来发送消息给大厅客户端。
需要注意的是,你的消息回调函数可能在大厅客户端初始化以前就接收到消息,除了接收到连接信息,大厅客户端改变连接设置或断开连接时,回调函数也会接收到消息。大厅客户端也能直接的发送消息到你的消息管理器上。
Note 最好使用多线程来接收消息。为了正确的管理消息,lobbied application回调函数应该具有多入口(re-entrant)。
 楼主| 发表于 2005-12-29 13:41:57 | 显示全部楼层

DirectPlay SDK中文翻译Understanding DirectPlay(3)


DirectPlay Callback Functions and Multithreading Issues

作者:杨冰(源代码之光)
E-mail:iceryeah2000@163.com
创建时间:
2002-10-24
最后修改时间:
2002-10-26

备注:
感觉这章翻译的不是很透彻,可能是因为多线程的知识比较欠缺


DirectPlay需要你注册几个回调函数来管理消息的响应。DirectPlay可以同时处理多个线程任务。DirectPlay通过线程池(thread pool)的技术来完成对多线程的管理,你所用的线程是这个池子所提供的。线程池的大小是通过Windows2000的进程处理准则规定的。这方面的知识你可以查看Mircrosoft Developer Network documents或者Win32 的多线程参考部分。
为了正确且可靠的从DirectPlay回调处接收到数据,你最好使用多线程同步技术。同步技术将有助你保持线程安全。

微软的操作系统提供三种方法来保持在多线程中数据的同步。

1 Mutex Objects
2 Semaphore Objects
3 Critical Section Objects

在DirectPlay Voice例子中使用了Critical Section Objects技术来同步数据。如果你希望使用前两种方法,在Microsoft Platform SDK中有查。同步技术的运用需要有较强的能力,SDK废话太多,就是说这个技术很不容易运用。
DirectPlay线程模块已经被最大程度的优化,在执行"send"操作和"indication"消息时(包括接收消息),没有线程设置开关,也就是不允许多个线程同时执行这两项操作,每次send只有一个线程,其它线程进行等待。(这段话翻译的不好:there are no thread context switches during "send" operations and during "indication" messages, including receive messages.)

DirectPlay Networking Callbacks
DirectPlay用于网络得回调函数是PFNDPNMESSAGEHANDLER类型的。依靠这种类型的网络会话,你可以用IDirectPlay8Peer::Initialize, IDirectPlay8Client::Initialize, 和IDirectPlay8Server::Initialize来注册回调函数。

同步问题
当在回调函数处理过程中,必须使用一个同步对象来保持游戏数据可靠。
为了理解你的游戏数据如何成为不可靠的,可以这样来考虑,在回调响应中,第一个线程将一段数据添入到结构体。如果另外一个线程在第一个线程没有执行完毕之前,进入回调中,并且试图操作那个结构体中的数据(同一个内存块中)。因此,被第一个线程更新的结构被第二个线程重新覆盖,导致了数据的错误。请注意到这只是多线程中一个简单的情况。
在Implementing a DirectPlay Networking Callback Using Critical Section Objects有一个例子,讲述如何在会话中同步数据。

Worker Threads
你可以自己定义一个"Worker Threads"。Worker Threads是另外一个多线程程序,它基于DirectPlay回调函数来处理游戏数据。这种方法的作用是在DirectPlay回调线程中接收数据缓存,。一个新的线程被创建,并且一个消息被发送到你的Worker Threads回调中,来标记处理缓冲数据。

Multithreading Performance Issues and Asynchronous Operations
需要慎重考虑在回调过程中处理信息所花的时间来。如果你有大量的信息在一个回调过程中,并且你使用了数据锁定来同步线程数据,你就会遇到线程堵塞问题。

如果你选择了worker thread和在另外一个回调中进行游戏数据的处理补偿,你就增加了CPU的处理时间。如果你在worker thread中设置了一些非关键性的数据处理过程,数据处理会更加占用CPU时间。

你可以在回调过程中返回DPNSUCCESS_PENDING,创建一个数据缓冲指针,然后使这个指针在worker thread中有效。当worker thread处理完了游戏数据,你就可以调用ReturnBuffer方法,来完成上述步骤。(IDirectPlay8Peer、 IDirectPlay8Client所提供的ReturnBuffer方法)
发表于 2006-3-22 16:55:07 | 显示全部楼层

支持!顶!

发表于 2006-3-24 00:01:47 | 显示全部楼层
这个论坛是我找寻多时的~~~所以打算在这定居了
发表于 2006-3-26 20:17:01 | 显示全部楼层
wuque79定居了??
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-5-14 05:51

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表