El blog de Juan Palómez

13 junio 2008

Sincronizar hora por HTTP

Filed under: Uncategorized — Etiquetas: , , , , — thisisoneball @ 01:00

Esto sirve para casos en los que no se pueda usar NTP. En mi caso los dispositivos que tengo que sincronizar no dejan conectar al puerto de NTP (123), solo puede conectar a los puertos de HTTP y FTP, así que lo hago a través de HTTP.
Los servidores web devuelven la fecha en las cabeceras HTTP, por ejemplo:

HTTP/1.1 200 OK
Date: Thu, 12 Jun 2008 22:27:47 GMT
Server: Oracle-Application-Server-10g/10.1.2.2.0 Oracle-HTTP-Server
Last-Modified: Mon, 31 Mar 2008 17:00:37 GMT
ETag: “6555ee-168-47f118b5”
Accept-Ranges: bytes
Content-Length: 360
Connection: close
Content-Type: text/html

Así que se puede coger la fecha de ahí. Esto lo hace un programa llamado Htpdate:
http://www.clevervest.com/twiki/bin/view/HTP/WebHome
El código que pongo aquí es para Windows Mobile, ya que Htpdate no tiene versión para este sistema. Es bastante más simple que dicho programa, pero funciona.


SYSTEMTIME HTTPGetTime(LPTSTR server)
{
HINTERNET session, connection, request;
SYSTEMTIME time; DWORD size;

session = InternetOpen (L"HTTPGetTime", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
connection = InternetConnect (session, server, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, NULL);
request = HttpOpenRequest (connection, L"GET", L"/", NULL, NULL, NULL, NULL, NULL);
HttpSendRequest (request, NULL, 0, NULL, 0);
size = sizeof(time);
HttpQueryInfo (peticion, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, &time, &size, NULL);
InternetCloseHandle(request);
InternetCloseHandle(connection);
InternetCloseHandle(session);

return time;
}

El único parámetro que toma la función es el hostname de un servidor web. Sirve cualquiera (que esté en hora), pero es mejor usar uno lo más cercano posible.
La mecánica es bastante simple, conecta al servidor, hace una petición GET, recibe los datos y coge la fecha de las cabeceras HTTP. Las funciones de WinInet hacen casi todo el trabajo.
Esto está probado en Windows Mobile 5 pero debería funcionar en cualquier Windows.

La función devuelve la hora en GMT. Para sincronizar la hora del sistema sería por ejemplo así:


SYSTEMTIME time;

time = HTTPGetTime(L"www.rediris.es");
SetSystemTime(&time);

No es realmente exacto por el retardo que hay desde que el servidor devuelve la hora hasta que se cambia la hora del dispositivo, pero es bastante exacto. Como dice el autor de Htpdate, si puedes hazlo por NTP y si no por HTTP.

Posibles mejoras:

  • comprobación de los códigos de retorno de las funciones
  • usar HEAD en vez de GET: no hace falta bajar toda la pagina solo para leer las cabeceras

Dejar un comentario »

Aún no hay comentarios.

RSS feed for comments on this post. TrackBack URI

Responder

Por favor, inicia sesión con uno de estos métodos para publicar tu comentario:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Crea un blog o un sitio web gratuitos con WordPress.com.

A %d blogueros les gusta esto: