Синхронизация переменной между клиентом и сервером

Скажем, у меня есть переменная счетчика на стороне клиента. Когда я отправляю запрос на сервер, я отправляю значение этой переменной, а затем увеличиваю его на единицу (для следующего запроса к серверу). Сервер отслеживает этот счетчик независимо и проверяет, что счетчик, отправленный клиентом, на 1 больше, чем его собственная (серверная) копия счетчика. Это все нормально, но рассмотрим следующую ситуацию:

  1. Клиент отправляет, скажем, 23 на сервер.
  2. Сервер получает 23, проверяет его и увеличивает собственный счетчик до 23.
  3. Сервер возвращает клиенту код All-Okay

-НО-

На пути от сервера к клиенту код возврата повреждается. Таким образом, клиент думает, что сервер не обновил свой счетчик, и поэтому оставляет счетчик на стороне клиента равным 23. С этого момента клиент и сервер не синхронизированы.

Кто-нибудь знает какие-либо надежные схемы, которые работали бы перед лицом таких возможных повреждений / ошибок?

Спасибо,
Кэмерон

Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
3
0
555
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Если вы используете надежный протокол, такой как TCP, вам не нужно беспокоиться о том, что сообщение не дойдет до клиента.

Тем не менее, при работе клиент / сервер следует соблюдать идемпотентность всех операций. То есть каждая функция может вызываться один или несколько раз без каких-либо побочных эффектов. В этом случае у вас вообще не будет функции «приращения». Вместо этого у вас будет функция «установить».

Ответ принят как подходящий

Вместо использования линейно увеличивающегося счетчика вы можете использовать случайное значение «nonce», равное 64 битам энтропии или более. Когда сервер получает запрос от клиента, сервер проверяет, совпадает ли одноразовый номер с последним отправленным клиентом. Если да, то запрос обрабатывается, и сервер генерирует новое случайное значение nonce для отправки в ответ.

Сервер может сохранить два последних значения одноразового номера для отправки клиенту. Если клиент отправляет старое значение, то сервер предполагает, что самое последнее сообщение клиенту могло быть потеряно.

Вышеупомянутый метод предполагает, что ваша цель - предотвратить использование двумя разными клиентами одних и тех же учетных данных для связи с сервером. Преимущество использования метода nonce заключается в том, что следующее значение нелегко предсказать.

Да, это моя цель, но предсказуемость числа не была бы проблемой в моем конкретном случае. Я действительно думал о нонсенсе, но в совершенно другом направлении; Ваше решение очень чистое и быстрое. Спасибо!

Cameron 19.10.2008 03:23

Как насчет того, чтобы клиент не обновлял свою локальную копию до тех пор, пока сервер не подтвердит обновление счетчика сервера.

Так:

Клиент рассчитывает следующее значение Клиент отправляет следующее значение на сервер Сервер проверяет, является ли следующее значение допустимым (еще не просмотренным) Сервер обновляет счетчик до следующего значения (при необходимости) Сервер уведомляет клиента о получении следующего значения Клиент обновляет локальный счетчик до следующего значения

Если сервер не получает обновление клиента, клиент просто повторно отправляет вычисленное следующее значение. Если клиент не получает подтверждения следующего значения, он повторно отправляет следующее значение, но сервер, который уже видел его, не обновляет, а просто подтверждает. В конце концов, клиент видит сообщение сервера и продолжает. Это касается случая утерянных сообщений.

Если вас беспокоит коррупция, вычислите контрольную сумму сообщения и отправьте ее тоже. Пересчитайте контрольную сумму при получении и сравните ее с отправленной. Как правило, сетевой стек делает это за вас, поэтому я бы не стал особо беспокоиться об этом, если только вы не используете свой собственный протокол.

Другие вопросы по теме