Приветствую Вас Прохожий | Получать RSS-новости | Главная | Регистрация | Вход |
Меню сайта

Форма входа

Категория каталога
Разное [78]

Новое на сайте
Новые файлы


Случайные программы


Новые статьи

Центр обновления Windows...
Иконка для вашего сайта
10 полезных возможностей...
Тонкости анонимного серф...
Что делать, если появляе...

Последние новости

«Спорту» осталось недолг...
Eutelsat W7. 36E Радуга-...
Astra 1H. 19.2E
Профилактика на спутнике...
Радуга-Интернет на Eutel...

Облако тегов


Друзья сайта
Дискуссионный клуб
Шаблоны для uCoz, скрипты для uCoz  Желтые страницы по спутниковому и кабельному ТВ


Для проживающих в городе Иваново:

Ремонт и настройка вашего компьютера
Установка программ
Защита. Удаление вирусов

Оцифровка видео и аудио материалов с возможностью компьютерного монтажа

Создание небольших сайтов, персональных страничек

Монтаж и настройка спутникового Интернета
и телевидения...

и прочие компьютерные услуги...

По всем вопросам обращаться по тел. 89605108897


Счетчики
Были сегодня:



Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Главная » Статьи » Разное » Разное

Написание игрового интернет сервера на php

Введение

Наверняка, Вы играли в такую игру как "Warcraft 3". И было бы просто прекрасно, если Вы играли по Интернету, ибо в этом случае Вы бы могли созерцать и испытать в действии то, что называется "Battle.net". В любом случае я поясню. Это некий "портал" благодаря которому игроки всего Интернета могут запросто найти работающие игровые сервера не выходя из игры. Что значительно облегчает им жизнь, т.к. отпадает необходимость заранее договариваться с соперниками при помощи чатов и подобных средств.

То, о чем я буду говорить в этой статье, поможет Вам создать подобное для своей игрушки. Сам метод достаточно прост и почти не имеет отрицательных моментов. Из-за отсутствия информации по данной теме мне пришлось самому, методом проб и ошибок, писать подобный портал (далее "арена") для своего проекта TFK.

Описание метода


Итак, опишу то что нам понадобится для реализации:
- Хостинг с поддержкой php;
- Ваша игра с работоспособным сетевым кодом :).
Первый пункт я надеюсь не вызывает больших проблем у начинающих "игрописателей", т.к. существует множество сайтов, предоставляющих бесплатный домен с поддержкой php.
А вот со вторым пунктом придется немного попариться, впрочем, это уже тема для отдельной статьи...
Так как в данной статье я использовал PHP, то потребуется знание его основ. Впрочем, при желании, перевод на другой язык написания web страниц не составит большого труда.

  Итак, имеем в Интернете домен на котором размещен наш скрипт "арены". Есть игра-клиент, которой нужно узнать кол-во доступных серверов, и при необходимости создать свой.
  Что нам нужно от "арены"? Всего-навсего получить список серверов в виде "IP:Port IP:Port IP:Port..." и зарегистрировать новый.
  Как это будет происходить? Да очень просто! Посредством HTTP запросов.
  Так как нет идеальных решений, какие минусы у данного метода?
- Серверы находящиеся за шлюзом не будут видны остальным клиентам, т.к. даже сама игра-сервер без понятия на каком external порту она висит.
- При падении хостера (сайта) арена шлепнется вместе с ним! Но это относится уже к форс-мажорным обстоятельствам... ;).
  А какие же плюсы?
- Относительная простота реализации;
- Легко разместить такую арену в локальной сети;
- Не требует восстановления после различных ЧП :).

Реализация


В этом разделе описаны основные процедуры необходимые для воплощения нашей мечты в реальность. Работа с ареной делится на 2 части:
1) Подача HTTP запросов и обработка ответов игрой;
2) Обработка запроса скриптом на арене.

  Всего будет 2 вида запросов: view и ping.
  VIEW необходим для получения списка серверов. Будет выглядеть следующим образом:
Запрос : http://host/?action=arena&mode=view.
Ответ : 212.100.15.45:25666 192.10.38.212:25666.
Т.е. в ответе мы видим, что на данный момент на арене находятся 2 сервера на портах 25666.

  PING для оповещения арены о том что сервер жив и удалять его из списка пока нет никакой необходимости.  Вы могли заметить то, что нет запроса на регистрацию сервера на арене, т.к. в качестве регистрации выступает постоянный "ping" посылаемый им. Сам же запрос "ping" следует посылать раз в несколько десятков секунд (20-40).
Запрос : http://host/?action=arena&mode=ping&port=25666
Ответ нам абсолютно не нужен :).

Реализация на стороне игры


Соответственно нам теперь необходимо знать как отправить HTTP запрос и получить на него ответ. Все проще чем может показаться. Приведу всего одну процедуру использующую возможности WinSock:

function Arena(const mode: string; get: boolean): stringconst  host = 'host.ru';  port = 25666; var  wData : WSADATA;  addr : sockaddr_in;  sock : integer;  error : integer;  buf : array [0..1023] of Char;  str : string;  phe : PHostEnt; begin  //Инициализация сокета  Result := ''; WSAStartup($0101, wData); phe := gethostbyname(PChar(string(host))); if phe = nil thenbegin  WSACleanup;  Exit;  end; sock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if sock = INVALID_SOCKET thenbegin  WSACleanup;  Exit;  end; addr.sin_family := AF_INET; addr.sin_port := htons(80); addr.sin_addr := PInAddr(phe.h_addr_list^)^; error := connect(sock, addr, sizeof(addr)); if error = SOCKET_ERROR thenbegin  closesocket(sock);  WSACleanup;  Exit;  end;  // Составляем строку запроса  str := 'GET http://' + host + '/?action=arena&mode=' + mode; if mode = 'ping' then str := str + '&port=' + IntToStr(port); str := str + ' HTTP/1.0'#13#10#13#10;  // отправляем  send(sock, str[1], Length(str), 0);  // Если нужен ответ то принимаем  if get thenbegin  ZeroMemory(@buf, 1024);  error := recv(sock, buf, 1024, 0);  while error > 0 dobegin  Result := Result + Copy(buf, 0, error);  error := recv(sock, buf, 1024, 0);  endend;  // Закрываем сокет - завершаем работу с сетью  closesocket(sock); WSACleanup;     // Вырезаем из ответа то что нам нужно, т.е. отрезаем // HTTP заголовки  if get and Result <> '' then Result:=Copy(Result, pos(#13#10#13#10, Result)+4,  Length(Result)); end;

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

 Str := Arena('view', true); // для получения списка серверов  Arena('ping', false); // сообщить арене что наш сервер  // живее всех живых 

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

procedure Arena_PingThread; begin  Arena('ping', false); end;    procedure Arena_Ping; var  id : DWORD; begin  CreateThread(nil, 128, @Arena_PingThread, nil, 0, id); end;

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

Реализация на стороне интернет сервера


Итак, с игрой разобрались, теперь осталось написать скрипт!
В запросах мы посылаем ключевое слово " action=arena " благодаря чему помимо арены на данном домене может висеть полноценный сайт.
Для того, чтобы определить адресуется ли данный запрос арене, в index.php необходимо (желательно в самом начале) написать следующее:

 if ($action == 'arena') {  include 'arena.php';  die(); }

   Это означает, что в случае того, когда захотят "пообщаться" с ареной, будет запущен скрипт арены для обработки запроса и дальнейшее выполнение скрипта index.php прекратится.

А вот и сам код arena.php:

 = 1024 && $port <= 65500))  $port = 25666;  // Читаем файл-список  $lst = file($list_file);  // В переменной $time теперь хранится текущее время  $time = time();  $j = -1;  $i = 0;  // Удаляем "мертвецов" и попутно ищем адрес отправителя  // в этом списке  while ($i < count($lst)) {  $lst[$i] = trim($lst[$i]);  list($l_ip, $l_port, $l_time) = explode(":", $lst[$i]);  // Если время с предыдущего пинга превысило 45 секунд  // - его явно уже нет  if ($l_time < ($time - 45)) {  for ($t = $i; $t < count($lst) - 1; $t++)  $lst[$t] = $lst[$t + 1];  unset($lst[count($lst) - 1]);  continue;  }  if ($l_ip == $ip) $j = $i;  $i++;  }  // Обработка запроса  switch ($mode) {  case 'view':  for ($i = 0; $i < Count($lst); $i++) {  // Вывод очередного IP:Port из списка  list($l_ip, $l_port, $l_time) = explode(":", $lst[$i]);  echo $l_ip.':'.$l_port.' ';  }  break;  case 'ping':  if ($j == -1)  // Если пингуется впервые, значит новый сервер - добавляем  array_push($lst, $ip.':'.$port.':'.$time);  else {  // Обновляем информацию для сервера  // Заметьте, что при смене порта на сервере  // на арене он тоже изменится  list($l_ip, $l_port, $l_time) = explode(":", $lst[$j]);  $lst[$j] = $l_ip.':'.$port.':'.$time;  }  break;  }  // Обновляем список серверов в файле-списке  $f = fopen($list_file, "a+");  flock($f, LOCK_EX);  ftruncate($f, 0);  for ($i = 0; $i < count($lst); $i++)  fwrite($f, $lst[$i]."\n");  fflush($f);  flock($f, LOCK_UN);  fclose($f); ?>

   Файл со списком серверов должен находиться в "db/arena_list.txt" с атрибутами разрешающими его изменение.
Вот собственно и все! Дальше дело стоит за Вашей фантазией...

Удачи!

Категория: Разное | Добавил: Himik (28.04.2009)
Просмотров: 1045 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Copyright Himik © 2026 Хостинг от uCoz