Pregunta

Digamos que tengo una variable de contador del lado del cliente. Cuando envío una solicitud al servidor, envío el valor de esta variable y luego la incrementé en uno (para la siguiente solicitud al servidor). El servidor realiza un seguimiento de este contador de forma independiente, y comprueba que el recuento enviado por el cliente sea 1 más que su propia copia (del lado del servidor). Todo esto está bien y es excelente, pero considere la siguiente situación:

  1. El cliente envía, digamos, 23 al servidor.
  2. El servidor recibe 23, lo valida e incrementa su propio contador a 23.
  3. El servidor devuelve el código All-Okay al cliente

-Pero-

A lo largo del camino del servidor al cliente, el código de retorno se corrompe. Por lo tanto, el cliente piensa que el servidor no actualizó su contador, por lo que deja el contador del lado del cliente en 23. A partir de este punto, el cliente y el servidor no están sincronizados.

¿Alguien sabe algún esquema robusto que funcionaría ante tal posible corrupción / errores?

Gracias,
Cameron

¿Fue útil?

Solución

En lugar de usar un contador que aumenta linealmente, puedes usar un &ce; &ce; nonce " Valor de unos buenos 64 bits de entropía o más. Cuando el servidor recibe una solicitud del cliente, el servidor verifica si el nonce coincide con el último que envió al cliente. Si es así, entonces la solicitud se procesa y el servidor genera un nuevo valor aleatorio de nonce para enviar la respuesta.

El servidor puede mantener los últimos dos valores de nonce para enviar al cliente. Si el cliente envía el valor anterior, entonces el servidor asume que el mensaje más reciente al cliente podría haberse perdido.

El método anterior asume que su objetivo es evitar que dos clientes diferentes utilicen las mismas credenciales para comunicarse con el servidor. La ventaja de usar el método nonce es que el siguiente valor no se puede predecir fácilmente.

Otros consejos

La respuesta fácil es hacer que uno de los clientes o servidores sea el propietario del recurso, en lugar de que ambos tengan su propia copia del recurso.

Sin embargo, si está utilizando un protocolo confiable como TCP, no tiene que preocuparse por el mensaje que no llega al cliente.

Una buena cosa a seguir cuando se hace trabajar el cliente / servidor es hacer que todas las operaciones sean idempotentes. Es decir, cada función podría llamarse una o varias veces sin ningún efecto secundario. En este caso, no tendrías una función de 'incremento' en absoluto. En su lugar, tendrías una función de 'conjunto'.

¿Qué tal si el cliente no actualiza su copia local hasta que el servidor reconozca la actualización del contador del servidor?

Entonces:

El cliente calcula el siguiente valor El cliente envía el siguiente valor al servidor El servidor comprueba que el siguiente valor es válido (no se ha visto) Las actualizaciones del servidor son contrarias al siguiente valor (si es necesario) El servidor notifica al cliente que se ha recibido el siguiente valor El cliente actualiza el contador local al siguiente valor

Si el servidor no recibe la actualización del cliente, el cliente simplemente reenvía el siguiente valor calculado. Si el cliente no recibe la siguiente confirmación de valor, reenviará el siguiente valor, pero el servidor que ya lo ha visto no se actualiza, solo confirma. Finalmente, el cliente ve el mensaje del servidor y continúa. Esto cubre el caso de mensajes perdidos.

Si le preocupa la corrupción, calcule una suma de comprobación en el mensaje y envíela también. Vuelva a calcular la suma de comprobación al recibirla y compárela con la enviada. Sin embargo, generalmente la pila de la red hace esto por ti, así que no me preocuparía demasiado si no ejecutas tu propio protocolo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top