Какова правильная логика обновления клиента игры?

Всем привет. Появилась необходимость в создании приложения, являющегося своего родом "лаунчером" (запускатором) для одной игры.
Единственная загвоздка, с которой я столкнулся - правильное обновление файлов игры.
Видов обновления может быть два:
  • Полное обновление
  • Частичное обновление

Если с первым пунктом все более-менее понятно (архив со всеми файлами загружаем и распаковываем), то со вторым пунктом не особо. Нет, конечно, можно при запуске приложения проверять версию программы и сравнивать с последней, той, что на сервере. Если локального файла версии нет, то качать полное обновление и прописывать версию из архива с этим обновлением, после чего снова сравнивать версию и если различается, то качать патч для этой версии и накатывать обновление сверху.

Вопрос первый: Насколько эффективно и эстетично обновление посредством загрузки патчей? То есть, версия будет иметь формат: 3.2.11.25. При запуске приложения/проверки наличия обновлений и загрузки обновлений будет проверяться версия. Если версия не соответствует, будет осуществляться проверка на то, какая из блоков цифр в версии отличается. То есть, если у пользователя версия 3.2.11.10, а на сервере 3.2.11.25, то качаться будут версии с *.*.*.10 по *.*.*.25 по очереди и накатывать патчи каждой из этих версий. А на сервере будет храниться какой нибудь файл с версиями, где они все будут перечисляться.

Вопрос второй: Как по-вашему мнению реализовано это у Steam? Загрузка по частям заголовками? Трафик во-время загрузки файлов идет через 80 порт с серверов Valve и content-type там application/octet-stream. Значит я прав? Но ведь не один большой файл таким образом качается, а много мелких, значит это просто отдача файлов таким образом у них осуществляется.
Как у них осуществляется проверка наличия даже самого ненужного файла? Удалил файл из каталога, а он берет и докачивает его. Проверяет перед запуском все каталоги на время изменения и сравнивает с серверными?

Вопрос третий: Насколько эффективно будет сравнивать время изменения каталогов у пользователя и сравнивать с серверными? Ведь если даже в самой глубокой директории был изменен/удален/создан файл, то самый верхний по иерархии каталог будет иметь дату изменения ту, когда был затронут файл. Соответственно, таким образом можно избежать большого количества рекурсивных проверок.
И, соответственно, обновиться будет проще. Удаляем измененный каталог и закачиваем заново.

Какое ваше мнение? Можете что то подсказать по-этому поводу?
  • Вопрос задан
  • 949 просмотров
Пригласить эксперта
Ответы на вопрос 7
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Из личного опыта: imho самое правильное это иметь неразрывную цепочку обновлений с первой версии до текущей, т.е 1>2, 2>3, 3>4 итд.
Периодически для чистой установки выпускать мажорные версии, - но при этом все равно иметь неразрывную цепочку обновлений.

Делать патчи вида 1>4, 2>4 итд - по моему опыту архи неправильно, т.к создает огромные риски неявных багов + затраты на сборку таких патчей.

По факту для пользователя нет проблемы установить много обновлений.

Будет осуществляться проверка на то, какая из блоков цифр в версии отличается.
Это Вы какие то мелкие частности обсуждаете.

Как у них осуществляется проверка наличия даже самого ненужного файла? Удалил файл из каталога, а он берет и докачивает его. Проверяет перед запуском все каталоги на время изменения и сравнивает с серверными?

Вопрос третий: Насколько эффективно будет сравнивать время изменения каталогов у пользователя и сравнивать с серверными? Ведь если даже в самой глубокой директории был изменен/удален/создан файл, то самый верхний по иерархии каталог будет иметь дату изменения ту, когда был затронут файл. Соответственно, таким образом можно избежать большого количества рекурсивных проверок.
И, соответственно, обновиться будет проще. Удаляем измененный каталог и закачиваем заново.
Привязываться к дате изменений - не лучшая идея. Проверка обходит каталоги рекурсивно, сравнивает не только список файлов но и их хеши. Почитайте как работает dropbox/яндекс.диск, да тот же торрент наконец
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Есть версия и есть хеш-сумма текущей версии всех данных приложения (файлы + БД).
При запуске - проверяются оба значения.
При несоответствии - выполняется операция синхронизации:
1. Выявление различий
2. Подготовка списка изменений относительно текущей версии у пользователя
3. Резервирование текущей версии пользователя
4. Загрузка всех необходимых файлов на устройство пользователя. (с возможностью докачки при разрыве соединения)
5. Выполнение изменений.
6. Проверка сделанных изменений (п.1)
7. Удаление резервной копии (созданную в п.3)
При прерывании любого из пунктов (сел аккумулятор у ПК или смартфона и прочее) - всегда должна быть возможность продолжить обновление с прерванного шага.
Ответ написан
Комментировать
@Alexander1705
Честно говоря, я с этим не сталкивался, но я бы попробовал сделать так:
Допустим, мы выпускаем новую версию - 2.46. При этом на сервер мы заливаем полную версию для чистой установки или для обновления с очень старых версий, и делаем n-ное количество патчей 2.45to2.46, 2.44to2.46, 2.43to2.46... Так, если пользователь отстаёт на несколько версий, он просто загрузит минимально необходимую разницу между его версией и актуальной, если же у пользователя очень старая версия, он скачивает заново весь клиент.
Таким образом минимизируется количество загрузок для пользователя, а следовательно уменьшится нагрузка и на сервер.
Ответ написан
@Neonoviiwolf
Flutter developer
Сервак сообщает актуальную версию программы, если нет совпадения, то сбрасывает хеш всех файлов новой версии программы, дальше программа на стороне клиента обходит рекурсивно каждый файл и сравнивает хеш, если не совпадает/не находит, качает с сервера. После полной загрузки обновления, изменяет версию ПО.
Тут вам и лишний ничего не скачает без необходимости, решит проблему обрывов соединения и решит проблему в случаи утраты/удаления/подмены файлов
Ответ написан
VGrabko
@VGrabko
Golang, Php, Js
Сервер отдаёт файл в котором указана дата последнего изменения отнсительно часового пояса юзера.

Юзер проверяет дату изменения файлов. И пишет их в массив
Юзер шлёт массив "не совпавших дат" и сервер в ответ отдаёт json с хешами для файлов

Потом проверяем хеши для этих файлов (в друг с часовым поясом намутили)
И если изменился загружаем (или даём серверу их список и он генерит в ответ архив с изменёнными файлами)
Ответ написан
Комментировать
@Sing303
Патчи
- Не эффективно
- Слишком сложно, чревато ошибками
- Усложнится поддержка и скорость выпуска патча, его тестирование

Как можно сделать (упрощённая схема)
1. Получаем с сервера список файлов и их хешей (всех)
2. Проверяем есть ли у пользователя все эти файлы (если хеш не корректен, считаем что файла нет)
3. Закачиваем по 1 запакованному файлу с сервера (не архив со всеми файлами, а именно по одному)
4. Распаковываем файлы, с заменой
5. Наслаждаемся обновлённой версией

Можно не считать хеш постоянно, а сохранять значение хеша локально и если дата файла изменилась, тогда считать хеш снова.
Данная схема очень проста, нет никаких патчей, качаются только те файлы, которые нужны, не нужно даже хранить номер версии, т.к. проверка по файлам.
Ответ написан
@dponyatov
Поднимите свой git-сервер для бинарных релизов и открытых скриптов, раз уж Microsoft за 20 лет не разродился apt update. В особо извращенных случаях можно даже отдавать часть исходников, и собирать stand-alone gcc на клиенте с оптимизацией -arch=host.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы