Как стать автором
Обновить

Комментарии 33

на клиенте хранить локальное время: localEventTime1,… localEventTimeN
на момент передачи передавать последнее локальное время: localTransmitTime
на сервере пересчитать на серверное время для N-ого события: clientX.serverEventTimeN = serverTransmitTime — (localTransmitTime — localEventTimeN)
Это сработает, только если между localEventTime1 и localEventTimeN время не слетит ещё раз
подписывайся на события смены времени и обновляй локальные временные метки

кейсов можно придумать кучу, все зависит от того, насколько их решения трудозатратны/ценны для бизнеса
Боюсь, обновить метки после вытаскивания батарейки на неопределённый срок будет проблематично
> Другие способы?
Передавать разницу времени между событиями:
Событие1: было 115секунд назад
Событие2: было 23 секунды назад
Событие3: 0 секунд назад(последнее)

> Есть идеи, что не так с японцами и филиппинцами?
Думается мне, что там много любителей игр на смартфонах, в которых реализованы разного рода Cooldown'ы: когда перезарядка умения/способности/предмета/строительства занимает определенное время. Например: здание достроится через 24 часа. Ты меняешь дату в телефоне и вуаля — здание уже достроено. А перемотав сразу на месяц ты увидишь, что на твоих счетах в виртуальных банках скопилась огромная сумма. Только думаю, что некоторые просто забывает вернуть дату назад.

Есть еще предположение о Филиппинах, что телефоны производят синхронизацию часовых поясов с базовыми станциями, и есть предположение что раз беда по всей стране, то их настаривают криворукие неопытные умельцы.
У японцев очень популярны мобильные игры и много мобильных геймеров, в некоторых играх, достаточно популярных, действует финт ушами, позволяющий получить жизни (читай возможность играть) простым переводом часов вперед. Чтоб часы не сбивать, можно просто переводить числа в календаре. Сам по той же причине из-за таймкиллера живу в июле)
Вот я подозревал игры, но не понимаю как жеж разработчики этих игр не закроют такую дыру. Для этих игр интернет же нужен всё-таки.
Если прям совсем закрыть такую «дыру», то в игру будут играть еще меньше. Те, кто очень хочет играть — пусть так и делают, никому хуже не будет. Если таких задротов выгнать из игры, то она потеряет в популярности, и уж точно наберет среди знакомых антирейтинги, мол: «эта игра настолько жестокая, что забанила меня, не советую играть в неё!», в то время как такие задроты вполне неплохо делают рекламу твоей игре.

А те, кто так делать не додумался — с них и можно стричь деньги
Тоже мне проблема! Каким бы странным время на клиенте не было, разница между ним и временем сервера в любом случае либо вообще фиксированная, либо поддаётся статистическому усреднению. Таким образом, за конечное (весьма небольшое) число запросов/ответов, эту разницу можно вычислить с точностью, достаточной для любых практических применений. У пользователя может быть какой угодно часовой пояс, и дата может быть по китайскому календарю. Главное, чтобы у него время шло строго вперёд со скоростью одна клиентская секунда за секунду сервера.
Клиентское время:
Даёт точные данные о порядке событий на клиенте и времени между ними

Не даёт, банальное обновление времени по ntp/от сотовой сети или перевод часов ломает эту линейность времени на ура. В равной степени это относится и к server-side ts, но там оно обычно более контролируемо.

Я в целом согласен, идеального в мире ничего нет. Но думается, что время не так часто переводится. В большой картине эти выбросы должны будут усредниться.
Батарейка в компьютере садится. В зависимости от чипсета начинаются сначала мягкие глюки — время начинает спешить или отставать с заметной скоростью, затем начинает страдать календарь.
Но эта проблема всплывает очень быстро — как только пытаешься воспользоваться безопасным соединением система начинает ругаться на недействительные сертификаты, которые либо ещё не выданы либо уже просрочены. Но пока пользователь столкнётся с проблемой и решит её проходит время, он запускает приложение и сервер видит неправильное и странное время на клиенте. Самый правильный способ избегать таких проблем — настойчиво предупреждать клиента что даты сервер/клиент отличаются более чем на 2 суток(с запасом на часовые пояса и т.д.), а если отличаются больше чем на неделю — не допускать работу такого клиента.
Если такие проблемы со временем, то не лучше ли использовать просто время приема данных на сервере + номер события. Ну и как подсказывают дополнительно хранить разницу во времени между событиями если хочется временные характеристики.
НЛО прилетело и опубликовало эту надпись здесь
Проблема в том, что эта схема не учитывает лаг, возникающий из-за того, что запрос и ответ требуют некоторого времени. Но направление мысли в принципе верное. Источник времени должен быть единым для всех. И поскольку клиентов много, то этим источником должен быть сервер. А клиентские часы должны использоваться строго в режиме таймера. Только для того, чтобы замерять интервалы между событиями.
Идея Mixim333 наиболее подходящая под задачу, сам задумался о нечто подобном. А лаг можно приблизительно рассчитать, несколько раз послав запрос на сервер и замерив время получения ответа, затем усреднить эти данные, тем самым вычислив приблизительную задержку самой сети.
Только лучше никому об этом не говорите. Я за такое решение чуть раньше минус получил :)

посмотрите на то, как работает ntp, всё давно придумано

Пробелма в том что єто надо будет делать постоянно. На каждую отправку данных надо будет измерять задержку сети, а не только в момент первичной синхронизации — со временем задержка может меняться от 10мс до пары секунд в зависимости от загрузки каналов передачи данных, изменения могут быть как длительные так и кратковременные.
А зачем постоянно? Один раз получили наиболее точный timestamp и с момента получения запустили таймер, а дальше уже отталкиваемся от показаний таймера.
И через месяц аптайма получим ошибку в 15...30 секунд. Если повезёт, конечно, порядка 5 секунд.
Вот это дискретизация! Если нужно делать что-то чаще, чем раз в месяц, то значит это нужно делать постоянно :)
Клиент не должен ничего прибавлять, что ему помешает прибавить на год вперёд? С таким же успехом можно просто отправлять время прошедшее с запуска клиента.
Но и тут подстерегает ряд засад — как бы ни выкручивались но время на сервере и на клиенте идёт 1) с разным темпом, 2) с разрывами.
Что если клиент подключен к серверу и аптайм соединения составляет год? За это время на клиенте время уйти может на час-другой а то и больше. Я вот видел сервер у которого часы шли на 1-2 сек в сутки быстрее и это ещё вполне приемлемая точность. Если там прикрутить периодическую синхронизацию времени, то будет возникать проблема в момент синхронизации — некоторые события внезапно придут в будущем или прошлом нарушив последовательность.
Так же надо предусмотреть ситуацию когда клиент уйдёт в гибернацию на час-другой например, а потом вернётся — счётчик времени может быть нарушен в зависимости от способа реализации подсчёта времени.
И если на физической машине можно обнаружить событие входа в гибернацию и выхода, то как быть с виртуальными машинами где вообще может не быть такого признака?
По этой причине в Win7 и старше нет подсчёта времени аптайма, только время последнего старта…
Если там прикрутить периодическую синхронизацию времени, то будет возникать проблема в момент синхронизации — некоторые события внезапно придут в будущем или прошлом нарушив последовательность.


В нормальных ОС ядро уже давно умеет небольшие подстройки делать не нарушая направление течения субъективного времени в userspace. Например, adjtime:
If the adjustment in delta is positive, then the system clock is speeded up by some small percentage (i.e., by adding a small amount of time to the clock value in each second) until the adjustment has been completed. If the adjustment in delta is negative, then the clock is slowed down in a similar fashion.
Это до тех пор пока приложение будет обращать внимание только на секунды, а когда оно берёт системное время в микросекундах и на основании этого числа выставляет приоритет событий проблема возвращается — между моментами этого маленького изменения события могут внезапно получить одинаковую метку времени. Вероятность только уменьшается а проблема остаётся.
НЛО прилетело и опубликовало эту надпись здесь
Даже если не ломать у таймера будет постоянно накапливаться ошибка. К тому же нет причин не доверять системному счетчику микросекунд, который как раз и служит для этих целей и реализован аппаратно в каждом ядре процессора. Но даже эти счётчики могут рассинхронизироваться из-за ошибки БИОСа на AMD-процессорах.
И даже если всё будет реализовано идеально, время между клиентом и сервером неизбежно будут расходится, при аптайме в месяц-другой ошибка запросто набежит в пол минуты и больше. Что с этим делать?

И кроме того, требовать модуля ядра для игрушки (или прав суперпользователя, если аппаратные таймеры экспонированы в userspace) — несколько слишком.

НЛО прилетело и опубликовало эту надпись здесь
Я тоже не думал о таком счётчике, пока не столкнулся с проблемой ТВ-тюнера на двухядерном AMD-процессоре, суть заключалась в том что приём команд с пульта программно-аппаратный и сильно зависит от синхронизации ядер процессора, если система использует аппаратные счетчики и БИОС неправильно инициализирует ядра процессора(баг такой) они в дальнейшем начинают работать несинхронно, за пол часа набегает разница в сотни микросекунд и команды с пульта постепенно перестают распознаваться. Никогда бы до этого не додумался если бы не форум посвящённый этому тюнеру, проблема оказывается известная… И это проблема на ровном месте на локальном компьютере, что уж говорить об интернете и разной скорости хода системных часов, там эта разница набежит ещё быстрее.
Если вдруг кто наткнётся на аналогичную проблему, то решение заключается в том чтобы заставить ядро системы использовать программный таймер вместо аппаратного счётчика при помощи ключа /usepmtimer в boot.ini

Даже ссылку на проблему вспомнил… http://www.ice-graphics.com/ICEAffinity/IndexR.html
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории