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

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

Поиск | Правила конференции | Фотоальбом | Регистрация | Список пилотов | Профиль | Войти и проверить личные сообщения | Вход

   Страница 1 из 1
 
Поиск в этой теме:
Канал Игры Мечты: «Higload UDP сервер. Архитектура. Варианты решения.»
Варсик
 545 EGP


Рейтинг канала: 4(81)
Репутация: 117
Сообщения: 4039
Откуда: Москва
Зарегистрирован: 22.12.2002
Сервер MMORPG/FPS игры в космосе. Рассматривается физический сервер мира.

Начал искать инфу по UDP и как его сделать скоростным и... ненашел.

Итак - базовый сервер пишется так (Win и Nix):
сокет, баинд, луп из recvfrom.

Для Windows я ненашел нормального объяснения - можно-ли из нескольких потоков делать recvfrom или нет. Однако WSARecv говорит что несколько вызовов их разных потоков приведут к непредсказуемому поведению. То есть - вроде-бы нет. А значит - надо городить отдельный поток на луп из recvcrfom и шедуллить полученные данные в другие потоки, тем самым убивая скорость. Или делать локи на ресурс, что так-же убивает скорость. Более того, почитав маны о libev (например тут) я нашел замечательный кусок:
Цитата:
Early versions of winsocket's select only supported waiting for a maximum of 64 handles (probably owning to the fact that all windows kernels can only wait for 64 things at the same time internally; microsoft recommends spawning a chain of threads and wait for 63 handles and the previous thread in each. Great).
Да, сейчас уже есть IOCP и т.д., но все-равно... вдумчивое гугление скажет что IOCP все-равно не панацея. Погуглив еще я пришел к выводу (субъективному), что 100К клиентов на Windows не похендлишь. Оно тупо медленное.

Итак, огородились от Windows. Дальнейшее продумывание архитектуры сервера ограничило меня и от FreeBSD. Просто потому что у него нету CUDA. То есть драйверов для FreeBSD у nVidia с поддержкой CUDA нету.

Успокоившись и поняв что ОС будет Linux, а метод работы с ядром будет epoll - начал прикидывать архитектуру...

Основная мысль: CPU принимает UDP пакеты от игроков с их вводом и записывает это все в правильные участки памяти. По таймеру все это сгружается в GPU и там рассчитывается физика, коллижены, попадания и т.д. Результаты сгружаются в другую часть памяти и рассылаются клиентам и серверу игровой логики.

Собственно сейчас вопрос в том, как сделать наиболее эффективным 2 места:
1) Получить данные и положить в память
2) Послать данные.

Для начала первое.
Данные получаются через recvfrom по сигналу с epoll'а (вообще, скорее всего, будет libevent или libev, а может и нет Подмигиваю ). Обойти recvfrom не получается, так как буфферезированного получения датаграмм еще ни у кого нету. Вроде-бы libevent 2.1 будет уметь, но и то не факт.

И тут опять получается интересная вещь... Если мы в цикле спамим recvfrom'ами, то потоки будут морозиться. И, как следствие, будем много переключений контекста. А это убийство производительности.
Самое эффективное, на мой взгляд, решение:
Создаем потоков ~= кол-ву ядер. Все эти потоки начинают спамить recvfrom, как только получили датаграмму - по отправителю нашли место, куда записать и заного спамим. По id из датаграммы это делать нельзя, так как подмена пакетов и левые люди мешают играть обычным людям. Проблемы будут только у NAT'еров, если за одним NAT'ом будет более 65К пользователей, что странно и вряд-ли будет.

Вопросы такие:
1) Это не воспаленный бред сумашедшего?
2) У кого-нибудь есть опыт написания таких серверов? Мне со стороны архитектуры хотя-бы...
3) Если у кого-то есть свежие мысли - выскажите.

добавлено спустя 34 минуты:
Пришла новая мысль...

Исходя из расчетов, проведенных в этой теме - можно на каждого клиента отвести свой порт. И сейчас мы это используем...

Проблема сервера в том, что при 100К клиентах надо искать соотношение IP/Port - Pointer, где IP/Port - коннект клиента, а Pointer - ссылка на его данные. Это может решаться или перебором или бинарным поиском и поддержанием списка упорядоченным или хешированием, двойным хешированием и т.д., а можно сделать финт ушами...
Если мы для каждого пользователя отдаем один порт на одном интерфейсе, то мы можем использовать номер этого порта в качестве id. А в данных прописать IP/Порт. Дело в том, что IP/Порт имеют размер 6 байтов, а Порт и N интерфейса - 2 байта порт + интерфейсов... Ну 4 максимум. То есть получается ~ 250К возможных значений. А на это можно тупо массив сделать. То есть получается прямое отображение. Конечно, потом еще надо будет проверить на IP/Порт, но это и так надо делать...

добавлено спустя 44 минуты:
Эм... А можно одним ударом прослушивать ВСЕ порты на определенном интерфейсе? ))

добавлено спустя 53 минуты:
Эм... В замешательстве... Как прослушать - нашел... либо libpcap либо
Код:
socket(PF_PACKET,SOCK_PACKET,htons(ETH_P_ALL));
А как при этом посылать сообщения?
_________________
WARNING: By reading this post you accept that this post is genius.

Последний раз редактировалось: Варсик (07:48 16-01-2013), всего редактировалось 3 раз(а)
    Добавлено: 07:48 16-01-2013   
VBKesha
 817 EGP


Рейтинг канала: 3(31)
Репутация: 132
Сообщения: 3329
Откуда: обл.Брянская г. Трубчевск
Зарегистрирован: 07.12.2005
Варсик :
Исходя из расчетов, проведенных в этой теме - можно на каждого клиента отвести свой порт. И сейчас мы это используем...

А что это вам даст? Какой смысл в куче портах на сервере?

Варсик :
Проблема сервера в том, что при 100К клиентах надо искать соотношение IP/Port - Pointer, где IP/Port - коннект клиента, а Pointer - ссылка на его данные. Это может решаться или перебором или бинарным поиском и поддержанием списка упорядоченным или хешированием, двойным хешированием и т.д., а можно сделать финт ушами...

А что если при конекте присваивать ID пользователю, и заставлять его передавать его в каждом пакете, а на сервере держать связь между ID и IP:Port. Для 100К на ID достаточно 3х байт, и поиск имхо делать проще. Если сделать массив на все 3 байта длинной, и на 6+4(на указатель 4 байта хватит?) размерностью элемента то получается около 160 метров памяти что вроде как и жирно и ИМХО стразу решит все проблемы.
Варсик :
А как при этом посылать сообщения?

Можно как минимум сделать ещё один сокет для отправки.
_________________
JumpGate. Quantar Optimus.
Jumpgate(TM) . . . welcome to your next life . . . There's nothing you can't do
    Добавлено: 09:31 16-01-2013   
Варсик
 545 EGP


Рейтинг канала: 4(81)
Репутация: 117
Сообщения: 4039
Откуда: Москва
Зарегистрирован: 22.12.2002
VBKesha :
А что это вам даст? Какой смысл в куче портах на сервере?
О! Я сейчас расскажу... Если пользователю не присваивать свой порт, то надо делать поиск в таблице по IP/Порту. А если каждому свой, то по локальному порту можно сразу посчитать оффсет и проверить - тот-ли это пользователь. Нету поиска. Грубо говоря:
TablePointer + LocalPort * SizeOf(TableEntry). Это константное вычисление. А не поиск. И не надо держать хеши или упорядоченную таблицу.
VBKesha :
А что если при конекте присваивать ID пользователю, и заставлять его передавать его в каждом пакете, а на сервере держать связь между ID и IP:Port.
Тот факт, что пакет может прилететь с левого коннекта, а так-же - это влияет на размер пакета. Я еще подумаю над тем, чтобы в пакет зерно меняющееся засунуть, чтобы обойти вариант, когда ты подделываешь пакеты.
VBKesha :
Можно как минимум сделать ещё один сокет для отправки.
Нельзя. Сокет надо баиндить. А баинд задает порт. А конкретный порт - это проблема с NAT'ами (они создают временный туннель... То есть когда ты от себя посылаешь пакет на удаленный IP Порт, то они считают что лететь будет именно с этого порта, а не с другого. Так UDP NAT работает в большинстве случаев). А если баиндить 65К сокетов, то это слишком большая трата ресурсов.
_________________
WARNING: By reading this post you accept that this post is genius.
    Добавлено: 15:52 16-01-2013   
VBKesha
 817 EGP


Рейтинг канала: 3(31)
Репутация: 132
Сообщения: 3329
Откуда: обл.Брянская г. Трубчевск
Зарегистрирован: 07.12.2005
Варсик :
Тот факт, что пакет может прилететь с левого коннекта, а так-же - это влияет на размер пакета. Я еще подумаю над тем, чтобы в пакет зерно меняющееся засунуть, чтобы обойти вариант, когда ты подделываешь пакеты.

Так в вашем способе всё остатся также только вместо ID выступает порт назначения? Да и 3 байта по моему вполне допустимая затрата.
Варсик :
Нельзя. Сокет надо баиндить. А баинд задает порт. А конкретный порт - это проблема с NAT'ами

Ох вы что собрались сервер на 100к держать на сером IP за натом? Или я не понял и вы хотите слушать все порты на клиенте, тут я вообще тогда в замешательстве зачем это надо?
_________________
JumpGate. Quantar Optimus.
Jumpgate(TM) . . . welcome to your next life . . . There's nothing you can't do
    Добавлено: 16:06 16-01-2013   
Варсик
 545 EGP


Рейтинг канала: 4(81)
Репутация: 117
Сообщения: 4039
Откуда: Москва
Зарегистрирован: 22.12.2002
VBKesha :
Так в вашем способе всё остатся также только вместо ID выступает порт назначения? Да и 3 байта по моему вполне допустимая затрата.
При посылке на сервер - да... Возможно вы правы... Я подумаю. Я как-то со стороны сервера все смотрю...
VBKesha :
Ох вы что собрались сервер на 100к держать на сером IP за натом? Или я не понял и вы хотите слушать все порты на клиенте, тут я вообще тогда в замешательстве зачем это надо?
Нет... Вы немного не поняли... Когда клиент через NAT начинает гнать UDP нат считает что с сервера датаграмма прилетит с того-же порта, на которой улетела с локала. А так как у меня в текущей архитектуре каждому пользователь свой серверный порт, то надо делать 65К сокетов на каждый порт. А это ресурсы.

А надо это для того, чтобы не заниматься поиском связки IP/Порт в таблице пользователей. Опять-таки ID с клиента и меняющийся ключ в принципе должны спасти... Однако мне не нравится то, что это нагрузка на протокол. А он сейчас максимально сжатый.
_________________
WARNING: By reading this post you accept that this post is genius.
    Добавлено: 16:16 16-01-2013   
Варсик
 545 EGP


Рейтинг канала: 4(81)
Репутация: 117
Сообщения: 4039
Откуда: Москва
Зарегистрирован: 22.12.2002
VBKesha :
Так в вашем способе всё остатся также только вместо ID выступает порт назначения? Да и 3 байта по моему вполне допустимая затрата.
Кстати... Спасибо за пинок... ID пользователя будет пересылаться с клиента на сервер. Заодно пошел в свой шит и увидел что там есть 4 байта свободных. Туда рандом и засунем.
_________________
WARNING: By reading this post you accept that this post is genius.
    Добавлено: 17:22 16-01-2013   
Канал Игры Мечты: «Higload UDP сервер. Архитектура. Варианты решения.»
 
  
Показать: 
Предыдущая тема | Следующая тема |
К списку каналов | Наверх страницы
Цитата не в тему: ...может тебе еще и ключи от Прометея, где шершни лежат?

  » Higload UDP сервер. Архитектура. Варианты решения. | страница 1
Каналы: Новости | Elite | Elite: Dangerous | Freelancer | Star Citizen | X-Tension/X-BTF | X2: The Threat | X3: Reunion | X3: Terran Conflict | X Rebirth | X4: Foundations | EVE Online | Orbiter | Kerbal Space Program | Evochron | VoidExpanse | Космические Миры | Онлайновые игры | Другие игры | Цифровая дистрибуция | play.elite-games.ru | ЗВ 2: Гражданская война | Творчество | Железо | Игра Мечты | Сайт
   Дизайн Elite Games V5 beta.18