C#. Как реализовать выполнение действий на сервере в real-time?
Давайте опишу суть вопроса на примере многопользовательской онлайн-игры. Допустим имеем некоторою игру, где имеется функционал "построить юнит". Данный юнит строится не сразу, а n-ое количество времени (5 минут, допустим). Пользователь-игрок инициирует постройку юнита. Как на стороне сервера можно (а лучше, как нужно?) реализовать данное "отложенное событие", чтобы через пять минут количество юнитов у игрока увеличилось на один?
Что для этого лучше всего использовать и в какую сторону смотреть: quartz, timer, etc?
За первую ссылку огромное спасибо! Я ещё не досмотрел до конца, но в принципе идея понятна + я знаком с SignalR.
Возможно я забегаю вперёд, но в данном видео уроке не решается задача, описанная мной. Да, используя SignalR/WebSocket/Socket.IO возможно использовать сервер, как связующее звено между клиентами. Таким образом можно передавать сообщения в чате, координаты игрока при его движении или результат при взаимодействии игроков (при выстреле, например, это попал/не попал).
Но если игрок закрывает клиент, то он перестаёт существовать для остальных участников. Мой пример был описан на основе таких игровых процессов, как крафт, т.е. данное действие не оказывает прямого влияния на других игроков, но это действие должно быть выполнено не зависимо от того, запущен ли клиент. Если вы играете в браузерную игру, где можно, допустим, отправить юниты в атаку на другого игрока, и происходит этот поход в течении 3-х часов, то я пока не имею понятия, как SignalR может мне помочь.
На реальном примере браузерки:
1 при начале крафта пишем в базу что игрок крафтит(чтобы залокать его), и пишем datetime когда конец крафта
2 на клиенте запускаем обратный таймер который раз в н сек опрашивает сервер что там крафтом, сервер возвращает разницу между текущим серверным временем и временем конца крафта, клиент смотрит разницу между клиентским обратным отсчетом и серверным, если нужно корректирует.
3 на сервере есть таймер который раз в н сек достает всех игроков у которых время конца крафта уже прошло по сравнению с текущим временем, запускает для каждого обработку конца крафта. у меня таймер висел в статике на старте приложения и залокан чтоб не пробуксовывал. но мне кажется такое решение плохое и лучше использовать owin типа quartz или вообще службу windows
Спасибо за ответ! В вашем варианте, как мне кажется, будет потеряна точность со стороны сервера, так как таймер работает через определённые промежутки времени + время на обработку всех данных (если юзеров >1000, то как быстро это будет?).
можно на обработку каждого юзера открыть новый поток и будет в параллель.
главное строить приложение таким образом чтобы при полном сбое, (к примеру пул упал, в датацентре свет мигнул, сервер из стойки на пол упал и тд) приложение поднялось и корректно отработало повторно. к примеру если в конце крафта выдается вещь то чтобы её выдало точно только 1 раз.
посекундной точности мало? можно попробовать сделать список таймеров с обработкой. только вот надо бы его вписать в базу и уметь оттуда его достать и поднять все таймеры при рестарте сервера к примеру.
Уже выкладывал тут код для подобного вопроса, такое решение мне нравится низким потреблением ресурсов, на все про все один таймер. Работает стабильно. Состояние можно легко свопить на диск и восстанавливать, при рестарте сервера.