netlib.narod.ru< Назад | Оглавление | Далее >

Введение в DirectPlay

DirectPlay — это решение Microsoft для работы с сетями. Хотя в нескольких последних версиях DirectPlay подвергался серьезным изменениям, кажется, что в версии 8 Microsoft удалось реализовать действительно простую для использования систему. Фактически, настолько простую, что вы начнете работать с сетью прежде, чем узнаете это.

ПРИМЕЧАНИЕ
Чтобы использовать DirectPlay в ваших проектах, убедитесь, что включили заголовочные файлы Dplay8.h и DPAddr.h, а также указали в списке компоновки библиотеки DPlay.lib и DXGuid.lib.

 

ПРИМЕЧАНИЕ
Я знаю, о чем вы думаете — что делает весь этот материал о DirectX версии 8 в книге, посвященной использованию DirectX версии 9?! Не беспокойтесь, мой друг, Microsoft решила оставить неизменной 8 версию интерфейсов в DirectX SDK версии 9 (девятой версии интерфейсов не существует), так что информация, которую вы найдете здесь, применима к DirectX как 8, так и 9 версий.

Сетевые объекты

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


Таблица 5.1. COM-объекты DirectPlay



Объект Описание

IDirectPlay8Client Объект клиента сети. Устанавливает соединение с сервером.
IDirectPlay8Server Объект сервера. Устанавливает соединение с клиентом.
IDirectPlay8Peer Объект одноранговой сети. Устанавливает соединения с другими одноранговыми клиентами.
IDirectPlay8Address Объект, который хранит (и создает) сетевой адрес.


 

ПРИМЕЧАНИЕ
Крупномасштабные ролевые игры обычно для эффективной работы требуют использования модели клиент/сервер, поэтому я не буду в этой книге обсуждать одноранговые сети. За примерами их использования обратитесь к документации DirectX SDK и книгам, перечисленным в приложении A. Я рекомендую в качестве источника информации об использовании одноранговых сетей в играх книгу Тодда Барона «Программирование многопользовательских игр».

Чтобы подключиться к удаленной системе (или запустить ведущий узел) вы конструируете сетевой адрес, используя интерфейс IDirectPlay8Address (показанный в таблице 5.1). Его единственная задача — создать и хранить единственный сетевой адрес.

ПРИМЕЧАНИЕ
Как я упоминал ранее, сессия — это период времени в течение которого работает ведущий узел, либо вы подключены к удаленной системе. Когда соединение разрывается, сессия завершается. У каждой сессии есть уникальные свойства, такие как имя, пароль (если необходим), максимально возможное число пользователей и т.д. Более подробно о сессиях мы поговорим в разделе «Конфигурирование данных сессии» далее в этой главе.

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

Работа с игроками

В терминах DirectPlay игрок (player) — это отдельное подключение, соединяющее вас с другим компьютером в сети. На одном компьютере может быть несколько игроков, но обычно используется только один. Фактически, серверу для идентификации также назначается игрок.

Каждый игрок получает идентификатор (Player ID), который система использует для направления сообщений отдельному игроку. Эти идентификаторы — единственный надежный метод определения игроков, так что ваша программа должна отслеживать их.

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

Взаимоотношения между игроками и группами показаны на рис. 5.5. Нет никаких ограничений на количество игроков в группе и на количество групп, которые вы можете создать. Как видно на рис. 5.5, группы (обозначенные прямоугольниками) могут входить в другие группы (группы 1 и 2 входят в группу 3). Обратите внимание, что игроки 7 и 8 изолированны от групп; для DirectPlay не имеет значения, входит игрок в группу или нет.


Рис. 5.5. Восемь игроков подключены к сеансу игры

Рис. 5.5. Восемь игроков подключены к сеансу игры. Шесть игроков относятся к группе (или к двум группам), а два игрока находятся отдельно от всех групп


Независимо от того, используете вы группы или нет, системы игроков, как только установлено соединение, могут взаимодействовать друг с другом через сообщения.

Сетевые сообщения

Сообщение (message) — это категоризированный пакет данных, завернутый в простую структуру. У каждого сообщения есть определенный смысл, ему назначен макрос (они показаны в таблице 5.2) и оно зависит от используемой сетевой модели. Например, объект клиента никогда не получит сообщение, предназначенное для однорангового объекта.


Таблица 5.2. Стандартные сообщения DirectPlay



Макрос сообщения Описание

DPN_MSGID_ADD_PLAYER_TO_GROUP Игрок добавлен в существующую группу.
DPN_MSGID_APPLICATION_DESC Запрошены данные приложения.
DPN_MSGID_ASYNC_OP_COMPLETE Асинхронная операция отправки данных завершена.
DPN_MSGID_CLIENT_INFO Запрошены данные клиента.
DPN_MSGID_CONNECT_COMPLETE Сетевое подключение завершено.
DPN_MSGID_CREATE_GROUP Создана группа.
DPN_MSGID_CREATE_PLAYER Создан игрок.
DPN_MSGID_DESTROY_GROUP Группа уничтожена (удалена).
DPN_MSGID_DESTROY_PLAYER Игрок уничтожен (удален).
DPN_MSGID_ENUM_HOSTS_QUERY Сетевое приложение ищет другие для соединения.
DPN_MSGID_ENUM_HOSTS_QUERY Сетевое приложение ищет другие для соединения.
DPN_MSGID_ENUM_HOSTS_RESPONSE Сообщение позволяет вам отвечать на запрос хоста.
DPN_MSGID_GROUP_INFO Запрошены данные группы.
DPN_MSGID_HOST_MIGRATE Хост перемещает свои данные на другую систему из-за потери соединения.
DPN_MSGID_INDICATE_CONNECT Удаленная система пытается подключиться.
DPN_MSGID_INDICATED_CONNECT_ABORTED Подключенная удаленная система пытается разорвать соединение.
DPN_MSGID_PEER_INFO Запрошены одноранговые данные.
DPN_MSGID_RECEIVE Данные получены.
DPN_MSGID_REMOVE_PLAYER_FROM_GROUP Игрок удален из группы.
DPN_MSGID_RETURN_BUFFER DirectPlay завершил работу с предоставленным ему буфером.
DPN_MSGID_SEND_COMPLETE Данные успешно отправлены.
DPN_MSGID_SERVER_INFO Запрошены данные сервера.
DPN_MSGID_TERMINATE_SESSION Сетевая сессия прервана.


 

ПРИМЕЧАНИЕ
Хотя смысл некоторых сообщений сейчас может быть вам непонятен, описания дают отправную точку. Мы будем работать лишь с несколькими сообщениями, но это тот случай, когда чем меньше, тем лучше.

 

ПРИМЕЧАНИЕ
Описание сетевых сообщений DirectPlay и связанной с ними информации вы найдете в документации к DirectX SDK. Я рекомендую, чтобы создавая свой шедевр, вы держали этот документ открытым под рукой.

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

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

Асинхронная и синхронная работа

Первый вариант доставки, предлагаемый вам DirectPlay — это синхронная или асинхронная отправка сообщений. Это означает, что либо система возвращает вам управление после того, как получила команду отправить данные (асинхронная работа), либо она ждет, пока данные не будут успешно отправлены (синхронная работа).

Что лучше? Скорее всего, вы предпочтете асинхронный метод, поскольку он не задерживает работу системы, как это делает синхронный. Например, если вы хотите отправить большой объем данных и одновременно пытаетесь играть в игру, то не захотите прерывать процесс, ожидая, пока сеть пытается передать информацию. Просто сообщите, что нужно отправить, и позвольте DirectPlay заняться обработкой, а игроку продолжать игру, будто ничего не произошло.

Безопасность

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

Обратной стороной безопасной доставки является замедление работы системы, поскольку данные надо зашифровать перед отправкой и расшифровать после приема. Если вы передаете важную информацию, потери времени не имеют значения (но они остаются важными для игр).

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

Гарантированная доставка

DirectPlay может гарантировать доставку сообщений, точно так же, как некоторые транспортные компании гарантируют доставку отправляемых через них посылок. Просто пометьте сообщение как требующее гарантированной доставки, и будьте уверены, что DirectPlay доставит его до места назначения (за исключением случая разрыва соединения), непрерывно повторяя операцию отправки до успешного завершения. Использование гарантированной доставки заключается в указании уникального флага в вызываемой функции, что вы увидите чуть позже в разделе «Отправка сообщений сервера» этой главы.

За гарантированную доставку придется платить скоростью. Гарантированная доставка слишком медленна, чтобы использовать ее в реальных игровых ситуациях. Игры используют метод доставки UDP (User Datagram Protocol), который не заботится о том, получены ли данные (в противоположность методу доставки TCP, гарантирующему доставку). Вы можете подумать, что это сумашествие, но разобравшись в ситуации увидите, что игры очень часто отправляют обновленную информацию, и потеря небольшого количества данных время от времени вполне допустима.

Регулировка потока

Иногда ваша система может испытывать перегрузки, пытаясь обработать поток сообщений. Однако, в DirectPlay есть встроенная система регулировки потока сообщений, которая выкидывает сообщения с низким приоритетом из очереди.

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


Рис. 5.6. Механизм регулировки

Рис. 5.6. Механизм регулировки (вышибала) принимает или отвергает сообщения (посетителей) в зависимости от их важности


 

ПРИМЕЧАНИЕ
DirectPlay замечательно выполняет регулировку потока, так что обычно вам не треьуется менять его параметры по умолчанию.

От маленьких байтов к большим словам

Мир очень большой, все мы различны, и возникают ситуации, когда необходим посредник. Я говорю о языковом барьере, в частности о компьютерном языковом барьере.

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

Поскольку версии Windows в разных странах слегка отличаются, пользовательские системы можно настроить на использование символов Unicode. В результате вся система DirectPlay построена вокруг использования символов Unicode (для хранения каждого символа используется 16 бит вместо 8) и приспособлена к языкам, использующим более 255 символов. Я слышу ваш стон, но позвольте сказать, что в Windows есть все необходимые функции для преобразования из одного формата символов в другой, так что волноваться не о чем.

Идентификация приложений по GUID

Сетевых приложений так много, как отличить свои от чужих? Присвойте вашему приложению уникальный номер и позвольте устанавливать соединение только с теми приложениями, у которых есть тот же номер. Этот специальный номер, конечно же GUID (Global Unique Identification), знакомый Windows-программистам.

Создавая приложение, уделите минуту, чтобы назначить ему уникальный GUID и удостоверьтесь, что все приложения, которые будут соединяться с вашим по сети используют тот же самый GUID.

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


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz