Создание онлайн-игры: основы

Блоговая публикация пользователя: ProCoder Эта публикация была перенесена из личного блога пользователя в общие разделы уровок сайта.

Создание онлайн-игры: основы

Существует две основные схемы организации онлайн-игр.

1. Клиент – сервер.

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

Уроки OpenGL различных тематик: схема клиент - сервер. Рисунок 1. Схема «клиент – сервер».
2. Клиент – клиент.

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

Уроки OpenGL различных тематик: схема клиент - клиент. Рисунок 2. Схема «клиент – клиент».
Итак, разберемся все-таки, что делает сервер.

Что есть сервер?

Сервер - это такая вот штука, которая прослушивает нужный порт на предмет подключения. Порт - это точка доступа к серверу, к которой подключаются клиенты. Например, веб-сервер нашего уютненького http://esate.ru работает по порту 80. Чтобы подключиться к его веб-серверу, откроем клиент telnet в ОС Windows. (подробнее о его установке тут) или откроем "Команднуюстроку", и введем следующую команду:

Код:
/*http://esate.ru, ProCoder*/

telnet esate.ru 80

И получим HTML-код:

Код:
/*http://esate.ru, ProCoder*/

<html>
<head><title>400 Bad Request</title></head>
<bodybgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/0.7.67</center>
</body>
</html>

Клиент подключился к серверу esate.ru, сервер отправил ему ответ и отключил клиента от себя. Типичное поведение веб-сервера. Сразу стало ясно, что нам нужно, чтобы написать простой сервер. Нам нужно прослушивать определенный порт на наличие клиентов, как только он появится – решать, что с ним делать, но этим мы займемся чуть позже.

Мы будет использовать протокол TCP/IP.

У платформы .NET есть класс для организации сервера. Называется он TCPListener, а находится в пространстве имен System.Net.Sockets.

Для начала создадим консольный проект на версии .NET Framework 3.5, назовем его, например, EsateGameServer (первое, что пришло в голову).

И еще некоторые приготовления: класс, в котором содержится метод Main() назовем KernelModule. Класс сервера ServerModule.

Начнем.
В "ядре" сервера создаем глобальную ссылку на наш класс ServerModule.

Код:
/*http://esate.ru, ProCoder*/

using System;
using System.Net;
using System.Net.Sockets;

namespace EsateGameServer
{
   classKernelModule
   {
      public static ServerModule Server;
      public static void Main()
      {
         
      }
   }
}

А вот код класса ServerModule:

Код:
/*http://esate.ru, ProCoder*/

using System;
using System.Net;
using System.Net.Sockets;

namespace EsateGameServer
{
   public class ServerModule
   {
      privateTcpListener Server;
      publicServerModule(int Port)
      {
         Server = new TcpListener(IPAddress.Any, Port);
         /*============================================
          * IP Address.Any указанный вместо IP адреса
          * компьютера означает, что сервер будет про-
          * слушивать указанный порт на всех интерфей-
          * сах. Например, у вас к компьютеру подключен
          * интернет и локальная сеть, а значит сервер
          * будет прослушивать и IP интернет интерфейса
          * по указанному порту, и локальный IP.
          =============================================*/
      }
      
      public void Start()
      {
         Server.Start(); //запускаем слушателя
         while (true) // в бесконечном цикле.
         {
            TcpClient client = Server.AcceptTcpClient(); //создаем экземпляр TCPClient, и
                                //направляем ему подключившегося клиента
            Console.WriteLine("Client is connect to the server");
         }
      }
   }
}

В ядре пишем в метод Main() следующие строки:

Код:
/*http://esate.ru, ProCoder*/

Server = new ServerModule(256); //Задаем порт 256
Server.Start(); //стартуем

Теперь давайте скомпилируем и попробуем подключиться к нашему серверу с помощью telnet'а. Открываем консоль, и вводим:

Код:
/*http://esate.ru, ProCoder*/

telnet 127.0.0.1 256
Жмем Enter и в окне telnet'a получаем пустое окно, а в окне нашего сервера получаем сообщение о том, что клиент соединился с сервером. Отлично, если всё получилось именно так.

Мы написали простой сервер, который прослушивает 256 порт, но, если мы попробуем открыть второе окно telnet'a и присоединиться к нашему серверу, клиент не подключится. И правильно, мы ведь прослушиваем 256 порт в одном потоке, поэтому как только сервер словил клиента, он начинает обмен информацией, а про прослушку порта для других клиентов забывает.

Значит, нам необходимо сделать сервер многопоточным для одновременной обработки большого количества клиентов. Об этом и многом другом подробнее в следующие части.

Нет доступа к просмотру комментариев.

^