netlib.narod.ru | < Назад | Оглавление | Далее > |
DirectPlay — это решение Microsoft для работы с сетями. Хотя в нескольких последних версиях DirectPlay подвергался серьезным изменениям, кажется, что в версии 8 Microsoft удалось реализовать действительно простую для использования систему. Фактически, настолько простую, что вы начнете работать с сетью прежде, чем узнаете это.
Используя DirectPlay вы получаете доступ к трем, упомянутым ранее сетевым моделям: клиентской, серверной и одноранговой. У каждой есть свой объект интерфейса (все они описаны в таблице 5.1), и все предоставляют похожие функции.
Таблица 5.1. COM-объекты DirectPlay
Объект | Описание |
IDirectPlay8Client | Объект клиента сети. Устанавливает соединение с сервером. |
IDirectPlay8Server | Объект сервера. Устанавливает соединение с клиентом. |
IDirectPlay8Peer | Объект одноранговой сети. Устанавливает соединения с другими одноранговыми клиентами. |
IDirectPlay8Address | Объект, который хранит (и создает) сетевой адрес. |
Чтобы подключиться к удаленной системе (или запустить ведущий узел) вы конструируете сетевой адрес, используя интерфейс IDirectPlay8Address (показанный в таблице 5.1). Его единственная задача — создать и хранить единственный сетевой адрес.
Затем вы создаете сетевой объект и назначаете ему адрес, после чего все готово для запуска ведущего узла или подключения к удаленной системе. Запустив ведущий узел игры вы просто ждете, когда другие системы (то есть люди, использующие эти компьютеры) подключатся к вам, поле чего ваша система и удаленный компьютер начинают обмениваться между собой относящимися к игре сетевыми сообщениями. В DirectPlay такие удаленные системы (а также ваш компьютер) называются игроками (players).
В терминах DirectPlay игрок (player) — это отдельное подключение, соединяющее вас с другим компьютером в сети. На одном компьютере может быть несколько игроков, но обычно используется только один. Фактически, серверу для идентификации также назначается игрок.
Каждый игрок получает идентификатор (Player ID), который система использует для направления сообщений отдельному игроку. Эти идентификаторы — единственный надежный метод определения игроков, так что ваша программа должна отслеживать их.
В больших играх могут быть тысячи подключенных игроков. Чтобы улучшить работу с игроками, некоторые (или все) игроки могут быть объединены в группы (groups). Используя группы вы слегка упрощаете программирование, поскольку можете объединить в группу игроков, находящихся в одной локации игры (такой, как карта или уровень) и отправлять данные всей группе сразу, а не каждому игроку индивидуально. (Есть ряд других причин для использования групп, но эта — одна из наиболее важных.)
Взаимоотношения между игроками и группами показаны на рис. 5.5. Нет никаких ограничений на количество игроков в группе и на количество групп, которые вы можете создать. Как видно на рис. 5.5, группы (обозначенные прямоугольниками) могут входить в другие группы (группы 1 и 2 входят в группу 3). Обратите внимание, что игроки 7 и 8 изолированны от групп; для DirectPlay не имеет значения, входит игрок в группу или нет.
Рис. 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 — это синхронная или асинхронная отправка сообщений. Это означает, что либо система возвращает вам управление после того, как получила команду отправить данные (асинхронная работа), либо она ждет, пока данные не будут успешно отправлены (синхронная работа).
Что лучше? Скорее всего, вы предпочтете асинхронный метод, поскольку он не задерживает работу системы, как это делает синхронный. Например, если вы хотите отправить большой объем данных и одновременно пытаетесь играть в игру, то не захотите прерывать процесс, ожидая, пока сеть пытается передать информацию. Просто сообщите, что нужно отправить, и позвольте DirectPlay заняться обработкой, а игроку продолжать игру, будто ничего не произошло.
Страшно знать, что в любое время кто-то в сети может перехватывать и записывать ваши данные. Поэтому у вас есть возможность зашифровывать данные сообщений, что затрудняет хакерам чтение вашей драгоценной информации.
Обратной стороной безопасной доставки является замедление работы системы, поскольку данные надо зашифровать перед отправкой и расшифровать после приема. Если вы передаете важную информацию, потери времени не имеют значения (но они остаются важными для игр).
В DirectPlay есть встроенная поддержка безопасного обмена сообщениями. К счастью, для ее использования достаточно лишь установить соответствующий флаг в операции отправки. Теперь это бремя снято с ваших плеч.
DirectPlay может гарантировать доставку сообщений, точно так же, как некоторые транспортные компании гарантируют доставку отправляемых через них посылок. Просто пометьте сообщение как требующее гарантированной доставки, и будьте уверены, что DirectPlay доставит его до места назначения (за исключением случая разрыва соединения), непрерывно повторяя операцию отправки до успешного завершения. Использование гарантированной доставки заключается в указании уникального флага в вызываемой функции, что вы увидите чуть позже в разделе «Отправка сообщений сервера» этой главы.
За гарантированную доставку придется платить скоростью. Гарантированная доставка слишком медленна, чтобы использовать ее в реальных игровых ситуациях. Игры используют метод доставки UDP (User Datagram Protocol), который не заботится о том, получены ли данные (в противоположность методу доставки TCP, гарантирующему доставку). Вы можете подумать, что это сумашествие, но разобравшись в ситуации увидите, что игры очень часто отправляют обновленную информацию, и потеря небольшого количества данных время от времени вполне допустима.
Иногда ваша система может испытывать перегрузки, пытаясь обработать поток сообщений. Однако, в DirectPlay есть встроенная система регулировки потока сообщений, которая выкидывает сообщения с низким приоритетом из очереди.
Возможно, рис. 5.6 поможет визуально представить концепцию использования механизма регулирования. Взглянув на рисунок, представьте очередь людей, ожидающих перед входом в популярный ночной клуб. Каждый человек представляет отдельное сообщение, и вышибала (механизм регулирования) должен удалить наименее важные из очереди, когда заведение становится переполненным.
Рис. 5.6. Механизм регулировки (вышибала) принимает или отвергает сообщения (посетителей) в зависимости от их важности
Мир очень большой, все мы различны, и возникают ситуации, когда необходим посредник. Я говорю о языковом барьере, в частности о компьютерном языковом барьере.
DirectPlay введет вас в мир Unicode (если вы еще не знакомы с ним). Unicode — это универсальный стандарт, позволяющий различным программам и компьютерам совместно использовать информацию. Поскольку сеть может быть соединена с другой сетью, расположенной в любом месте мира, игроки могут жить в разных странах и говорить на разных языках.
Поскольку версии Windows в разных странах слегка отличаются, пользовательские системы можно настроить на использование символов Unicode. В результате вся система DirectPlay построена вокруг использования символов Unicode (для хранения каждого символа используется 16 бит вместо 8) и приспособлена к языкам, использующим более 255 символов. Я слышу ваш стон, но позвольте сказать, что в Windows есть все необходимые функции для преобразования из одного формата символов в другой, так что волноваться не о чем.
Сетевых приложений так много, как отличить свои от чужих? Присвойте вашему приложению уникальный номер и позвольте устанавливать соединение только с теми приложениями, у которых есть тот же номер. Этот специальный номер, конечно же GUID (Global Unique Identification), знакомый Windows-программистам.
Создавая приложение, уделите минуту, чтобы назначить ему уникальный GUID и удостоверьтесь, что все приложения, которые будут соединяться с вашим по сети используют тот же самый GUID.
Вот и все, что я хотел сейчас сказать об отправке данных. Ход выполнения от создания сетевого объекта DirectPlay до отправки и получения данных для разных типов объектов очень похож, так что в последующем изложении я буду переплетать отдельную информацию.
netlib.narod.ru | < Назад | Оглавление | Далее > |