c# synchronization clock

c# - ¿Cuál sería la mejor manera de sincronizar el tiempo de mi aplicación con el tiempo del servidor externo?



synchronization clock (3)

Estaba pensando en cambiar la hora local del sistema a la hora del servidor y luego usarla, pero apuesto a que hay otras formas de hacerlo. He estado tratando de encontrar algo así como un reloj en c #, pero no pude encontrar nada. Estoy recibiendo el tiempo del servidor en formato DateTime.

editar: necesito que mi aplicación se use mientras trabaja el mismo servidor. Solo quiero obtener el tiempo del servidor una vez y luego de eso, hacer que mi aplicación funcione en un ciclo while usando el tiempo que obtuve del servidor. Puede haber una diferencia entre el tiempo de mi sistema y el tiempo del servidor (incluso 5 segundos) y es por eso que quiero hacer esto.


La respuesta @ JonSkeet proporcionada para sincronizar los tiempos se ve bien, solo quería señalar algunas cosas.

Como ya dijo @Alexei, los usuarios requieren privilegios de administrador para poder cambiar su hora local (al menos en Windows), pero también puede haber otros problemas que pueden hacer que el tiempo no esté sincronizado (conexión a Internet, piratería, etc.). ) Esto significa que no hay garantía de que la hora del cliente sea igual a la hora del servidor, por lo que al menos deberá verificar la hora en que se recibió la solicitud en el servidor. Además, podría haber un problema de usabilidad aquí, ¿me gustaría que una aplicación pueda cambiar el horario de mi máquina local? Diablos no.

Para resumir las cosas:

  • Compruebe la hora de la solicitud en el servidor al menos
  • No cambie la hora de la máquina del cliente, pero muestre algún tipo de indicador en su aplicación

Cómo manejar el indicador en su aplicación se puede hacer de varias maneras.

  • Muestre un reloj en su aplicación (su idea inicial) que se sincroniza periódicamente con el servidor
  • Muestre algún tipo de cuenta regresiva ( "puede enviar después de x segundos ..." ), presione una solicitud de resetCountdown a los clientes cuando se recibe una solicitud.
  • Habilite un "botón de envío" o lo que sea que tenga, esto funcionaría de manera similar a la cuenta atrás.

Solo recuerda, es casi imposible validar una solicitud como este lado del cliente. ¡Entonces tienes que construir algunos controles en el servidor!

De hecho, quería escribir un comentario, pero se alargó un poco ... :)


Su servidor siempre debe guardar el tiempo en modo UTC.
Ahorre tiempo en UTC de esta manera en el servidor:

DateTime utcTime = new DateTime(0, DateTimeKind.Utc);

o:

DateTime utcTimeNow = DateTime.UtcNow;

En el cliente, cuando obtiene el tiempo que está almacenado en utc, puede pasarlo a la hora local de esta manera:

public DateTime ToLocalTime(DateTime utcTime) { //Assumes that even if utcTime kind is no properly deifned it is indeed UTC time DateTime serverTime= new DateTime(utcTime.Ticks, DateTimeKind.Utc); return TimeZoneInfo.ConvertTimeFromUtc(serverTime, m_localTimeZone); }

Si desea cambiar su zona horaria local, aquí hay un ejemplo de código sobre cómo leer la zona horaria para usar desde config:

string localTimeZoneId = sysParamsHelper.ReadString(LOCAL_TIME_ZONE_ID_KEY, LOCAL_TIME_ZONE_DEFAULT_ID); ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones(); foreach (TimeZoneInfo timeZoneInfo in timeZones) { if(timeZoneInfo.Id.Equals(localTimeZoneId)) { m_localTimeZone = timeZoneInfo; break; } } if (m_localTimeZone == null) { m_logger.Error(LogTopicEnum.AMR, "Could not find time zone with id: " + localTimeZoneId + " . will use default time zone (UTC)."); m_localTimeZone = TimeZoneInfo.Utc; }


No está del todo claro qué quiere decir, pero ciertamente podría crear su propia interfaz de IClock que usaría en todas partes en el código, y luego escribir una implementación de la que regularmente se sincroniza con su servidor (o con NTP).

Mi proyecto Noda Time ya utiliza la idea de un reloj inyectable, no para fines de sincronización, sino para la capacidad de prueba. (Un servicio de tiempo es básicamente una dependencia.) Básicamente la idea es viable :) Es muy posible que no encuentres nada que ya lo haga, pero no debería ser demasiado difícil de escribir. Sin embargo, le conviene pensar en cómo ajustar el tiempo, por ejemplo, si el tiempo del servidor supera las "últimas mediciones de tiempo del servidor + tiempo local", es posible que desee hacerlo gradualmente en lugar de tener un salto discreto.

Esto siempre asume que quieres que sea local para tu aplicación, por supuesto. Otra alternativa (que puede no ser adecuada, según su contexto) es requerir que el host ejecute un cliente de sincronización de tiempo ( creo que Windows lo hace de forma predeterminada en estos días) y simplemente comience a fallar si la diferencia entre su servidor y el cliente demasiado grande. (De todos modos, nunca va a estar exactamente sincronizado, o al menos no por mucho tiempo; tendrás que dejar espacio libre).