Microsoft DirectX 9.0 SDK Update (Summer 2003) |
Tutorial 1: Creating a DirectPlay Object and Enumerating Service Providers
This series of tutorials demonstrate how to implement a simple peer-to-peer multiplayer game using Microsoft® DirectPlay®. This tutorial outlines the initial steps: creating a DirectPlay object and enumerating the available network service providers. Subsequent tutorials build on this foundation to take you through the key steps needed to construct a simple peer-to-peer console application. Much of the information in these tutorials can also be applied to client/server applications. The complete sample code for this tutorial is included with the Microsoft DirectX® software development kit (SDK) and can be found at (SDK root)\Samples\C++\DirectPlay\Tutorials\Tut01_EnumSP.
For a general discussion of peer-to-peer applications, see Peer-to-Peer Sessions.
- User's Guide
- Creating a DirectPlay Peer Object
- Enumerating Service Providers
- Terminating a DirectPlay Application
User's Guide
When you run this tutorial sample, a window opens and the application displays the service providers found on your computer. To end the tutorial, click Exit.
Creating a DirectPlay Peer Object
One of the first things a peer-to-peer application must do is create and initialize a DirectPlay peer object (CLSID_DirectPlay8Peer). To create a DirectPlay peer object, call CoCreateInstance, and request a pointer to an IDirectPlay8Peer interface. All of your subsequent interaction with DirectPlay and your fellow players will be through this interface.
Once you have created the peer object, you must initialize it by calling the IDirectPlay8Peer::Initialize method. This method takes three parameters:
- A player context value
- A pointer to your callback message handling function
- A flag
The message handler is a key part of a DirectPlay application. You communicate with DirectPlay by calling methods on a DirectPlay interface. DirectPlay in turn communicates with your application by sending messages to your message handler, much like Microsoft Windows® sends messages to a window procedure. See DirectPlay Callback Functions and Multithreading Issues for details on how to implement a message handler.
The player context value is an application defined value that is returned each time a message is sent to your message handler. See Using Player Context Values for a discussion of how to handle player context values.
There is only one flag value that can be set, DPNINITIALIZE_DISABLEPARAMVAL. Setting this flag disables parameter validation for all DirectPlay methods. While setting this flag improves your application's performance, you should only do so with an application that has been thoroughly tested.
The following excerpt from the tutorial sample illustrates how to create and initialize a DirectPlay peer object.
#include <dplay8.h> . . . // Create the IDirectPlay8Peer Object hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay8Peer, (LPVOID*) &g_pDP ); // Initialize DirectPlay hr = g_pDP->Initialize(NULL, DirectPlayMessageHandler, 0 );
Enumerating Service Providers
DirectPlay is an application programming interface (API) that allows game players to easily connect with each other and exchange messages, regardless of the underlying transport protocol. It enables you to use one or more service providers when hosting, connecting to, or enumerating sessions. To determine which service providers are available on your system, DirectPlay allows your application to enumerate your system's valid installed service providers as well as their adapters.
To enumerate your service providers, call IDirectPlay8Peer::EnumServiceProviders. This method fills an application-supplied buffer with information about the valid service providers on your system. As you do not know the minimum size of the buffer prior to calling this method, you should call it twice. The first time, specify a zero-length buffer and the method returns the required size. Use this size value in your second method call and DirectPlay fills the buffer with valid data. See Getting DirectPlay Data for further information about DirectPlay enumeration.
The following excerpt from the tutorial sample illustrates how to enumerate available service providers.
DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL; DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = NULL; DWORD dwItems = 0; DWORD dwSize = 0; DWORD i; // Determine the required buffer size hr = g_pDP->EnumServiceProviders(NULL, NULL, NULL, &dwSize, &dwItems, 0); pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize]; //Fill the buffer with service provider information hr = g_pDP->EnumServiceProviders(NULL, NULL, pdnSPInfo, &dwSize, &dwItems, 0 ); // Print the provider descriptions pdnSPInfoEnum = pdnSPInfo; for (i = 0; i < dwItems; i++) { DXUtil_ConvertWideStringToGenericCch( strBuf, pdnSPInfoEnum->pwszName, 256 ); SendMessage( GetDlgItem( g_hDlg, IDC_PROVIDERS ), LB_ADDSTRING, 0, (LPARAM) strBuf ); pdnSPInfoEnum++; }
Terminating a DirectPlay Application
If a DirectPlay peer object was successfully initialized by calling IDirectPlay8Peer::Initialize, it should be closed by calling IDirectPlay8Peer::Close. You should then release all active objects before terminating the application. A DirectPlay object can be reused once it has been closed, provided that it is re-initialized by calling IDirectPlay8Peer::Initialize.
The following excerpt from the tutorial sample illustrates how to close and release DirectPlay objects.
hr = g_pDP->Close(0); g_pDP->Release(); g_pDP = NULL;