Recupération de l'heure d'un serveur NTP

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Recupération de l'heure d'un serveur NTP

Message 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 :)
Dernière modification par flaith le dim. 15/janv./2006 21:21, modifié 1 fois.
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message 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 :roll: ). Et ensuite de comparer avec une base géographique, le fuseau horaire auquel tu partiens. 8O

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 :lol:
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message 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 ! :?
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message 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
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message 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 :oops:
Merci de t'en occuper, sympa :wink:

sinon la V4 avec un unsigned long, ca va le faire !!!
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message 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.
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

C'est nickel Droopy :wink:
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message 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
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

Pinaise, 'gnifique 8O
Merci beaucoup :P
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message 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 :wink:
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message 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 :D
Dernière modification par Droopy le lun. 16/janv./2006 19:47, modifié 1 fois.
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

ImageImage
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Code modifié, ajout d'un timeout optionnel comme paramètre de connexion.
Avatar de l’utilisateur
Progi1984
Messages : 2659
Inscription : mar. 14/déc./2004 13:56
Localisation : France > Rennes
Contact :

Message par Progi1984 »

Il n'y a pas moyen de gérer les millisecondes ?
Répondre