Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming / GameProg / RPG_Programming_2ed.pdf
Скачиваний:
243
Добавлен:
12.02.2016
Размер:
12.06 Mб
Скачать

Глава 5. Работа с сетью с DirectPlay

Данные сессии клиента

Информация, которую надо установить в структуре данных сессии клиента включает имя и пароль сессии, к которой вы хотите подключиться, флаг модели клиент/сервер и GUID приложения. Убедитесь, что указали тот же GUID, что и для приложения сервера, чтобы они могли найти друг друга в сети. А вот пример:

// GUID приложения сервера

GUID AppGUID = { 0xede9493e, 0x6ac8, 0x4f15,

{0x8d, 0x1, 0x8b, 0x16, 0x32, 0x0, 0xb9, 0x66 } };

//Обнуляем структуру данных сессии и устанавливаем ее размер

DPN_APPLICATION_DESC dpad;

ZeroMemory(&dpad, sizeof(DPN_APPLICATION_DESC)); dpad.dwSize = sizeof(DPN_APPLICATION_DESC);

// Задаем имя и пароль сессии к которой подключаемся dpad.pwszSessioName = L"MySession"; dpad.pwszPassword = L"MyPassword";

//Устанавливаем GUID приложения dpad.guidApplication = AppGUID;

//Устанавливаем флаги модели клиент/сервер и использования пароля dpad.dwFlags = DPNSESSION_CLIENT_SERVER |

DPNSESSION_REQUIREPASSWORD;

Работа с сервером

Наконец-то начинается настоящее развлечение! Первый этап реальной работы с сетью — это создание сервера. Сервер действует как центральный процессор вашей сетевой игры. Все игроки подключаются к серверу через клиентское приложение и начинаемтся передача данных туда-сюда.

Сервер поддерживает синхронизацию данных и оповещает игроков о текущем состоянии игры. Хотя для небольших сетевых игр это, возможно, не самый быстрый метод, для крупномасштабных игр он является наилучшим, и поэтому я использую его в главе 15.

Вот завершенная функция, которая создает объект сервера и инициализирует его, устанавливая функцию обработки сообщений (пока очень простую), создает компоненты адреса и структуру данных сессии, а затем выполняет специальный вызов для открытия игровой сессии. В результате вызова этой функции вы получете указатель на сетевой объект

 

сервера.

 

// GUID сервера

 

GUID AppGUID = { 0xede9493e, 0x6ac8, 0x4f15,

 

{ 0x8d, 0x1, 0x8b, 0x16, 0x32, 0x0, 0xb9, 0x66 } };

 

// Прототип обработчика сообщений

 

HRESULT WINAPI ServerMsgHandler(PVOID pvUserContext,

 

DWORD dwMessageId, PVOID pMsgBuffer);

 

 

276

netlib.narod.ru

 

 

Джим Адамс

IDirectPlay8Server *StartNetworkServer(

 

char

*szSessionName, // Имя сессии (в ANSI)

char

*szPassword,

// Используемый пароль

DWORD

dwPort,

// (NULL если нет)

// Используемый порт

DWORD

dwMaxPlayers)

// Максимальное количество

{

 

// игроков

*pDPServer;

 

IDirectPlay8Server

 

IDirectPlay8Address

*pDPAddress;

 

DPN_APPLICATION_DESC dpad;

WCHAR wszSessionName[256];

WCHAR wszPassword[256];

// Создание и инициализация объекта сервера if(FAILED(DirectPlay8Create(&IID_IDirectPlay8Server,

(void**)&pDPServer, NULL)))

return NULL; if(FAILED(pDPServer->Initialize(pDPServer,

ServerMsgHandler, 0))) {

pDPServer->Release(); return NULL;

}

//Создание объекта адреса, установка поставщика услуг

//и порта

if(FAILED(DirectPlay8AddressCreate(

&IID_IDirectPlay8Address, (void**)&pDPAddress, NULL))) { pDPServer->Release();

return NULL;

}

pDPAddress->SetSP(&CLDID_DP8SP_TCPIP); pDPAddress->AddComponent(DPNA_KEY_PORT, &dwPort,

sizeof(DWORD), DPNA_DATATYPE_DWORD);

// Установка данных сессии

ZeroMemory(&dpad, sizeof(DPNA_APPLICATION_DESC)); dpad.dwSize = sizeof(DPNA_APPLICATION_DESC); dpad.dwFlags = DPNSESSION_CLIENT_SERVER;

// Установка имени сессии с преобразованием ANSI в Unicode mbstowcs(wszSessionName, szSessionName,

strlen(szSessionName) + 1); dpad.pwszSessionName = wszSessionName;

// Установка пароля (если надо) if(szPassword != NULL) {

mbstowcs(wszPassword, szPassword, strlen(szPassword)+1); dpad.pwszPassword = wszPassword;

dpad.dwFlags |= DPNSESSION_REQUIREPASSWORD;

}

// Установка максимальногоколичества игроков dpad.dwMaxPlayers = dwMaxPlayers;

Здесь я на секунду остановлюсь и познакомлю вас со специальной функцией узла, которая открывает сетевую сессию объекта сервера:

netlib.narod.ru

277

Глава 5. Работа с сетью с DirectPlay

HRESULT IDirectPlay8Server::Host(

// Данные сессии

const DPN_APPLICATION_DESC *const pdnAppDesc,

IDirectPlay8Address **const prgpDeviceInfo,

// Объект адреса

const DWORD cDeviceInfo,

//

1

const DPN_SECURITY_DESC *const pdpSecurity,

//

NULL

const DPN_SECURITY_CREDENTIALS *const pdpCredentials, //

NULL

VOID *const dwPlayerContext,

//

NULL

const DWORD dwFlags);

//

0

К счастью, для этой монстрообразной функции уже все готово. Вы уже создали объект адреса и инициализировали описание сессии, а все остальное — детские игрушки. Вот оставшаяся часть функции:

if(FAILED(pDPServer->Host(&dpad, &pDPAddress, 1, NULL, NULL, NULL, 0))) {

pDPAddress->Release(); pDPServer->Release(); return NULL;

}

//Освобождаем объект адреса - он больше не требуется pDPAddress->Release();

//Возвращаем объект сервера

return pDPServer;

}

//Функция серверного обработчика сообщений с размещенной на месте

//и готовой к употреблению конструкцией switch...case для сообщений

HRESULT WINAPI ServerMsgHandler(PVOID pvUserContext,

DWORD dwMessageId, PVOID pMsgBuffer)

{

//Определите здесь структуры сообщений DPNMSG_*

//Указатель на вызывающий объект сервера передается через

//пользовательский указатель при вызове Initialize

IDirectPlay8Server *pDPServer;

pDPServer = (IDirectPlay8Server*)pvUserContext;

switch(dwMessageId) {

//Добавьте здесь инструкции case для различных

//типов сообщений, например:

//case DPN_MSGID_CREATE_PLAYER:

//DPNMSG_CREATE_PLAYER dpcp;

//dpcp = (DPNMSG_CREATE_PLAYER*)pMsgBuffer;

//Делайте, что вам надо с этими данными и, когда закончите,

//верните флаг успеха

//return S_OK;

}

return E_FAIL;

}

Как видите, я снова вставил только скелет функции обработчика сообщений. Перед тем, как вы сможете начать работу с сообщениями, надо понять лежащую в их основе теорию. В следующих разделах мы начнем с относящихся к игрокам сообщений, поскольку они наиболее часто используются.

278

netlib.narod.ru

Соседние файлы в папке GameProg