Page 1 sur 2
Recupération de l'heure d'un serveur NTP
Publié : dim. 15/janv./2006 14:31
par flaith
hello tout le monde, je fait un prog me permettant de récupérer l'heure via un serveur ntp, j'ai donc fait ce code, mais mon soucis vient après avoir récupéré les données, comment les convertir en heure ???
NB : je n'ai pas besoin de lancer la commande
net time ...
ce n'est pas ce que je cherche !
le code
Code : Tout sélectionner
;-*************************
;-*** ***
;-*** UPTIME - Flaith ***
;-*** 15/01/2006 ***
;-*** ***
;-*************************
;--> CONSTANTES & GLOBALES
#CP = "134.59.1.5" ; ntp.unice.fr
#PSERV = 37
Global wVersionRequested.w
;--> MAKEWORD : concatene 2 valeurs byte en un word
Procedure.w MAKEWORD(LoByte.b, HiByte.b)
If HiByte & $80
ret_value = ((HiByte * $100) + LoByte) | $FFFF0000
Else
ret_value = (HiByte * $100) + LoByte
EndIf
ProcedureReturn ret_value
EndProcedure
; ******************************************************************************************
;-Initialise Winsock
wsaData.WSADATA ; WSADATA = structure de données pour
; l'implementation des sockets
wVersionRequested = MAKEWORD(1, 1) ; version WINSOCK.DLL 1.1 mini
If (Result = WSAStartup_(wVersionRequested, @wsaData)) <> #NO_ERROR
MessageRequester("Information", "La DLL WINSOCK ne supporte pas cette version !",0)
End
EndIf
;-Creation d'un socket
socket = SOCKET_(#AF_INET, #SOCK_STREAM, #IPPROTO_TCP)
If socket = #INVALID_SOCKET
MessageRequester("Erreur", "Erreur socket(): " + Str(WSAGetLastError_()),0)
WSACleanup_()
End
EndIf
;-Connection au socket
*ptr = sin.sockaddr_in
sin\sin_family = #AF_INET
sin\sin_addr = inet_addr_(#CP) ; converti une adresse IP en type "in_add"
sin\sin_port = htons_(#PSERV) ; converti au bon format et dans le bon ordre
If connect_(socket, *Ptr, SizeOf(sockaddr_in)) = #SOCKET_ERROR
MessageRequester("Erreur", "Impossible de se connecter au serveur " + #CP,0)
closesocket_(socket)
End
EndIf
;-Lecture des données
buffer.s = Space(32) ; 4 octets
recu = recv_(socket, @buffer, 4, 0) ; reception des données via le socket
time_ = ntohl_(buffer) ; converti au bon format et dans le bon ordre
; // ***** c'est ici , cette valeur qui me pose problème
time_ = time_ - 2208988800 ; soustrait 1970.0 - 1900.0
tt = Date()
Heure.s=FormatDate("%hh:%ii:%ss",time_)
;-Affichage de l'heure reçu
MessageRequester("Info","bytesRecv = "+Str(recu)+Chr(13)+Chr(10)+"time_ = "+Str(time_)+Chr(13)+Chr(10)+"Date = "+Str(tt)+Chr(13)+Chr(10)+"Heure = "+Heure,0)
closesocket_(socket)
WSACleanup_()
D'avance merci pour votre aide

Publié : dim. 15/janv./2006 16:52
par Gillou
Le principe serait de trouver l'adresse du premier routeur par lequel tu passes pour aller sur le net. De lui demander son lieu géographique (rayon du département normalement, à moins que ton fai te fournisse directement l'adresse d'un pilier de la backbone ex : si tu es à paris le pilier peut-être à Londres

). Et ensuite de comparer avec une base géographique, le fuseau horaire auquel tu partiens.
T'es pas obligé de faire ça, si tu es à peu près sûr de l'heure système (au quart d'heure près) (avec GetSystemTime_(sysTime.systemtime) (si tu déménage c'est foutu)
Je vais essayer de regarder sur le net, si je trouve des infos
J'allais oublié le plus simple tu demandes à l'utilisateur de choisir son lieu géographique

Publié : dim. 15/janv./2006 18:51
par flaith
Merci Gillou, mais pour le moment mon seul soucis est la variable "_time", ce que je récupère du serveur (ces 4 octets) je n'arrive pas à les convertir en heure/min/sec !

Publié : dim. 15/janv./2006 21:10
par Droopy
Publié : dim. 15/janv./2006 21:21
par Gillou
A ok, j'ai regardé ton code, ça à l'air correct sauf pour ce qui est des dates
time_ = time_ - 2208988800
purebasic ne supporte pas pour l'instant les nombres supérieures à 2147483647
je regarde en passant par les chaînes
Publié : dim. 15/janv./2006 21:30
par flaith
@Droopy : Merci pour le lien, je vais décortiquer le programme
@Gillou : c'est vrai que le long, j'aurais du le voir
Merci de t'en occuper, sympa
sinon la V4 avec un unsigned long, ca va le faire !!!
Publié : dim. 15/janv./2006 22:31
par Droopy
J'ai lu le code VB et fait ça :
Code : Tout sélectionner
;/ Récupération Heure depuis Serveur NTP
; Droopy 15/01/06 22H28 et 22secondes Heure NTP :)
; PureBasic 3.94
InitNetwork()
CnxionId= OpenNetworkConnection("time.ien.it",37) ; time.nist.gov / ntp1.fau.de
If CnxionId
;/ Attends que le serveur envoie des data
While NetworkClientEvent(CnxionId)=0
Delay(1)
Wend
;/ Réception des 4 octets
Buffer.s=Space(4)
ReceiveNetworkData(CnxionId,Buffer,4)
CloseNetworkConnection(CnxionId)
;/ Calcule l'heure
NTPTime=Asc(Left(Buffer,1))*255*255*255 + Asc(Mid(Buffer,2,1))*255*255 + Asc(Mid(Buffer,3,1))*255 + Asc(Right(Buffer,1)) + 2125010696
;/ Affiche l'heure
MessageRequester("NTP",FormatDate(" %dd/%mm/%yy %hh:%ii:%ss",NTPTime))
EndIf
Il n'y a plus qu'a gérer les fuseaux / gérer le temps de connexion au serveur comme ils l'indiquent sur le site VB.
Publié : dim. 15/janv./2006 22:34
par Gillou
C'est nickel Droopy

Publié : dim. 15/janv./2006 23:09
par Droopy
J'ai modifié un code de Fweil pour gérer les fuseaux
Code : Tout sélectionner
ProcedureDLL.s GetTimeZoneName()
GetTimeZoneInformation_(TimeZoneInfo.TIME_ZONE_INFORMATION)
While TimeZoneInfo\StandardName[i] <>0 And i <= 32
sStandardName.s + Chr(TimeZoneInfo\StandardName[i])
i + 1
Wend
ProcedureReturn sStandardName
EndProcedure
Procedure GetTimeZone() ; Hour to add to the UTC hour
GetTimeZoneInformation_(TimeZoneInfo.TIME_ZONE_INFORMATION)
Retour=TimeZoneInfo\bias/60
ProcedureReturn Retour
EndProcedure
Publié : dim. 15/janv./2006 23:11
par flaith
Pinaise, 'gnifique
Merci beaucoup

Publié : lun. 16/janv./2006 0:04
par Droopy
J'ai corrigé quelques bugs / fusionné mes deux posts / ajouté une fonction pour définir l'heure du système et ça donne ceci :
Code : Tout sélectionner
;/ Récupération Heure depuis Serveur NTP
; Droopy 15/01/06 + Fweil pour les fonctions de TimeZone
; PureBasic 3.94
ProcedureDLL.s GetTimeZoneName() ; Return Cities present in the Time Zone
;/ Author : Fweil
GetTimeZoneInformation_(TimeZoneInfo.TIME_ZONE_INFORMATION)
While TimeZoneInfo\StandardName[i] <>0 And i <= 32
sStandardName.s + Chr(TimeZoneInfo\StandardName[i])
i + 1
Wend
ProcedureReturn sStandardName
EndProcedure
ProcedureDLL GetTimeZone() ; Hour to add to the UTC hour
;/ Author : Fweil
GetTimeZoneInformation_(TimeZoneInfo.TIME_ZONE_INFORMATION)
Retour=-TimeZoneInfo\bias/60
ProcedureReturn Retour
EndProcedure
ProcedureDLL SetDate(Date)
Heure.SYSTEMTIME
Heure.SYSTEMTIME\wYear=Year(Date)
Heure.SYSTEMTIME\wMonth=Month(Date)
Heure.SYSTEMTIME\wDay=Day(Date)
Heure.SYSTEMTIME\wDayOfWeek=DayOfWeek(Date)
Heure.SYSTEMTIME\wHour=Hour(Date)
Heure.SYSTEMTIME\wMinute=Minute(Date)
Heure.SYSTEMTIME\wSecond=Second(Date)
SetSystemTime_(Heure)
EndProcedure
InitNetwork()
CnxionId= OpenNetworkConnection("time.ien.it",37) ; time.nist.gov / ntp1.fau.de
If CnxionId
;/ Attends que le serveur envoie des data
While NetworkClientEvent(CnxionId)=0
Delay(1)
Wend
;/ Réception des 4 octets
Buffer.s=Space(4)
ReceiveNetworkData(CnxionId,Buffer,4)
CloseNetworkConnection(CnxionId)
;/ Calcule l'heure
NTPTime=Asc(Left(Buffer,1))*16777216 + Asc(Mid(Buffer,2,1))*65536 + Asc(Mid(Buffer,3,1))*256 + Asc(Right(Buffer,1)) - 2840140800
NTPTime=AddDate(NTPTime,#PB_Date_Year,20) ; Comme NTPTime = secondes depuis 1990 et Date() = secondes depuis 1970 --> On ajoute 20 ans
;/ Défine l'heure du PC à l'heure NTP
SetDate(NTPTime)
;/ Affiche l'heure
Temp.s="Heure UTC : "+FormatDate(" %dd/%mm/%yy %hh:%ii:%ss",NTPTime)+#CR$
Temp+"Zone : "+GetTimeZoneName()+#CR$
Temp+"Décalage de : "+Str(GetTimeZone())+" heures"+#CR$
Temp+"Heure locale : "+FormatDate(" %dd/%mm/%yy %hh:%ii:%ss",NTPTime+GetTimeZone()*60*60)+#CR$
MessageRequester("UTC et NTP",Temp)
EndIf
Encore des fonctions en plus pour la prochaine Droopy Lib

Publié : lun. 16/janv./2006 0:29
par Droopy
Voici la dernière version : (modifié)
Code : Tout sélectionner
;/ Get Time from NTP Server / Set Local Time / Get Time Zone information
; Droopy 15/01/06 + Fweil for TimeZone functions
; PureBasic 3.94
ProcedureDLL.s GetTimeZoneName() ; Return the name of the Time Zone
;/ Author : Fweil
GetTimeZoneInformation_(TimeZoneInfo.TIME_ZONE_INFORMATION)
While TimeZoneInfo\StandardName[i] <>0 And i <= 32
sStandardName.s + Chr(TimeZoneInfo\StandardName[i])
i + 1
Wend
ProcedureReturn sStandardName
EndProcedure
ProcedureDLL GetTimeZone() ; Hour to add to the UTC hour
;/ Author : Fweil
GetTimeZoneInformation_(TimeZoneInfo.TIME_ZONE_INFORMATION)
Retour=-TimeZoneInfo\bias/60
ProcedureReturn Retour
EndProcedure
ProcedureDLL SetDate(Date) ; Set the System Date : Return 1 if success
Heure.SYSTEMTIME
Heure.SYSTEMTIME\wYear=Year(Date)
Heure.SYSTEMTIME\wMonth=Month(Date)
Heure.SYSTEMTIME\wDay=Day(Date)
Heure.SYSTEMTIME\wDayOfWeek=DayOfWeek(Date)
Heure.SYSTEMTIME\wHour=Hour(Date)
Heure.SYSTEMTIME\wMinute=Minute(Date)
Heure.SYSTEMTIME\wSecond=Second(Date)
If SetSystemTime_(Heure)
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
ProcedureDLL GetNTPTime(NTPServer.s,TimeOut) ; Ask a NTP Server and return the Date as PureBasic format / 0 if it could not be joined
; Server = time.ien.it / time.nist.gov / ntp1.fau.de
InitNetwork()
CnxionId= OpenNetworkConnection(NTPServer,37)
If CnxionId
;/ Wait until the Server Send Datas
While NetworkClientEvent(CnxionId)=0
Delay(1)
T+1
If T>TimeOut
ProcedureReturn 0
EndIf
Wend
;/ Wait until the Server Send Datas
While NetworkClientEvent(CnxionId)=0
Delay(1)
Wend
;/ Get four Bytes
Buffer.s=Space(4)
ReceiveNetworkData(CnxionId,Buffer,4)
CloseNetworkConnection(CnxionId)
;/ Calcule the Date as PureBasic Format ( UTC )
NTPTime=Asc(Left(Buffer,1))*16777216 + Asc(Mid(Buffer,2,1))*65536 + Asc(Mid(Buffer,3,1))*256 + Asc(Right(Buffer,1)) - 2840140800
NTPTime=AddDate(NTPTime,#PB_Date_Year,20) ; Add 20 years
ProcedureReturn NTPTime
Else
ProcedureReturn 0
EndIf
EndProcedure
ProcedureDLL GetNTPTime2(NTPServer.s) ; Default TimeOut = 120ms
ProcedureReturn GetNTPTime(NTPServer.s,120)
EndProcedure
;/ Test
NTPTime=GetNTPTime2("time.ien.it")
If NTPTime
;/ Set the Computer Time as NTP Time
SetDate(NTPTime)
;/ Show information about Hour
Temp.s="UTC Time : "+FormatDate(" %dd/%mm/%yy %hh:%ii:%ss",NTPTime)+#CR$
Temp+"Zone : "+GetTimeZoneName()+#CR$
Temp+"Shift : "+Str(GetTimeZone())+" hour(s)"+#CR$
Temp+"Local Time as US format : "+FormatDate(" %mm/%dd/%yy %hh:%ii:%ss",NTPTime+GetTimeZone()*60*60)+#CR$
Temp+"Local Time as French format : "+FormatDate(" %dd/%mm/%yy %hh:%ii:%ss",NTPTime+GetTimeZone()*60*60)+#CR$
MessageRequester("UTC et NTP",Temp)
EndIf
à compiler avec Tailbite car InitNetwork ne supporte pas d'être appelé deux fois

Publié : lun. 16/janv./2006 0:40
par flaith
Publié : lun. 16/janv./2006 19:48
par Droopy
Code modifié, ajout d'un timeout optionnel comme paramètre de connexion.
Publié : jeu. 16/nov./2006 12:17
par Progi1984
Il n'y a pas moyen de gérer les millisecondes ?