Обычный веб-запрос живёт до ответа и на этом умирает. Игровому серверу такого мало: он обязан сам, ничего не дожидаясь, сообщить клиенту, что рядом появился монстр, что по игроку прошёл удар, что открылась дверь. Значит, соединение должно держаться постоянно — и за это приходится платить.

Что даёт постоянное соединение
Входящие соединения обслуживает CLI-демон: он держит открытые сокеты и разбирает всё, что шлют игроки. На PHP эту роль закрывает workerman.
WebSocket — это не отдельная сеть, а набор правил поверх TCP: как выглядят заголовки, чем разделяются пакеты, как проходит рукопожатие. Сам TCP даёт две вещи, ради которых всё и затевается: гарантию доставки и порядок — пакеты придут ровно в той последовательности, в какой ушли. А постоянное соединение снимает расходы на установку нового при каждом обмене.

Никто не мешает написать поверх TCP собственный протокол — та же библиотека это позволяет. WebSocket выигрывает тем, что его уже понимает браузер.
У HTTP есть keep-alive, который удерживает соединение открытым, но оно закроется через несколько секунд простоя. Пошаговой игре этого хватит, реальному времени — нет.
Чем за это платишь
Гарантия доставки стоит времени: на пакет идёт подтверждение о получении. Пакеты выстраиваются друг за другом, а не летят параллельно. И к полезным данным на каждом сообщении добавляются служебные заголовки.
Рядом есть второй базовый протокол — UDP. Накладных расходов меньше, данные идут сплошным потоком, доставка не гарантируется вовсе. Он оправдан там, где поток настолько плотный, что потерять часть пакетов дешевле, чем ждать подтверждения: так устроены шутеры вроде Counter-Strike. Мне важнее гарантия — в 2D MMO потерянный пакет с уроном или перемещением ломает картину мира у игрока.

Сколько это держит на PHP
Теоретическая пропускная способность TCP на одном порту упирается в числа, к практике отношения не имеющие. Интереснее замеры на живом фреймворке.

В этих тестах workerman занимает:
1 место (с использованием php 8 и Jit пре компиляции php скриптов в некие "бинарники")
2 место - его модификация с заменой Apache и Nginx на HTTP сервер написанный на PHP слушающий порт сервера (те работает и определяется PHP как CLI , без запуска fpm workers). Документация на Китайском , но механика следующая : Singleton'ы (грубо говоря закешированные экземпляры классов) всех контроллеров, вызывающиеся в onMessage() (метод срабатывающий когда на порт сервера приходят данные посланные клиентом из браузера) с параметрами которые пришли в запросе и увеличенный параметр keep-alive (те между браузером и сервером устанавливается постоянное TCP соединение которое дольше остается открытым чем в том же Apache где этот параметр ~10 секунд) - нам не очень актуален этот фреймворк тк мы не будем использовать HTTP
3 и 8 место держат вариации с использование PostgreSql и без модификаций
В среднем — около 350 000 запросов в секунду. Рейтинг снят на HTTP, но включённый keep-alive заставляет сервер вести себя почти как WebSocket: соединения удерживаются.
Остаётся вопрос, много это или мало и сколько игроков получится держать онлайн. Упирается он уже не в сеть: узкое место — где лежит состояние мира и как быстро к нему обращаться.
Что было дальше
Тогда это был расчёт под будущий сервер. Сейчас на этой основе работает платформа: авторитарный сервер на PHP, открытый бесшовный мир, клиент на Unity и редактор, где игровая механика описывается текстом, а не правкой клиента. Куда это пришло — в последних частях серии.
История:
WebSocket
Выбор технологий, протокола и архитектурный шаблон Entity Component System
FPS, Ping, паузы между командами, интерполяция и экстраполяция
Event-driven паттерн, JSON-RPC и почему не сервисная (SOA) архитектура
Сетевая карта и задержка кадра (Latency frame) по RFC 2544 (1242)
Конвейер контента для MMO: импорт анимации, экипировка и обновление игры без патчей

