Seite 1 von 1

Zeitserver im Netzwerk über Port 123 und UDP abfragen

Verfasst: 20.09.2007 06:31
von Unimatrix Zero
Hallo zusammen,

hat jemand einen Tip oder einen Link für mich wie ich im Netzwerk bei einem Zeitserver über den Port 123 mit dem UDP Netzwerkprotokoll vorgehen muss um eine aktuelle Uhrzeit abfragen zu können?

Verfasst: 20.09.2007 13:59
von bobobo

Verfasst: 21.09.2007 15:45
von Unimatrix Zero
Hallo bobobo,

vielen Dank für den Link.

Hallo @all

Habe jetzt herausgefunden, dass der Zeitserver über UDP scheinbar erst antwortet, wenn ihm vorher der Befehl "/n" zugesendet wird.
Wenn ich es richtig verstanden habe, bekomme ich jetzt einen 64 Bit Wert zurück, wovon wohl die ersten 32 Bit den ganzahligen Anteil darstellen.
Hmm, habe jetzt schon alles mögliche probiert, bekomme es aber irgendwie nicht hin.
Hier mal das Codeschnipsel, dass ich mir unter Zuhilfenahme der Beispiele aus diesem Forum zusammengebastelt habe:

Code: Alles auswählen

Global  lBuffer.l
Global lNTPTime.l
Global Time.l 
Global Sekunden.q

SysTime.SYSTEMTIME

;Time-Server im Internet
Port.l = 123
TimerServerHost.s = "10.10.10.10"

TimeOutConter.l = 0
ServerTimeOut.l = 10000000
Command.s = "/n"



If InitNetwork() = 0
  MessageRequester("Fehler", "Netzwerk konnte nicht initialisiert werden!", 0)
  End
EndIf

;Verbindung zum Time-Server aufnehmen
ConnectionID = OpenNetworkConnection(TimerServerHost, Port, #PB_Network_UDP)

If ConnectionID
  SendNetworkData(ConnectionID, @Command, Len(Command))

Else
  MessageRequester("Fehler", "Verbindung zum Server fehlgeschlagen!", 0)
  End
EndIf

  Repeat
    ClientEvent.l = NetworkClientEvent(ConnectionID)
    If ClientEvent = 2 ;Der Zeit-Server schickt Zeitdaten
      lBuffer = AllocateMemory(8)
      retval.l = ReceiveNetworkData(ConnectionID , lBuffer, 8)
;       Sekunden = (PeekB(lBuffer+0)&$FF) << 56
;       Sekunden + (PeekB(lBuffer+1)&$FF) << 48
;       Sekunden + (PeekB(lBuffer+2)&$FF) << 40
;       Sekunden + (PeekB(lBuffer+3)&$FF) << 32
      Sekunden = (PeekB(lBuffer+0)&$FF) << 24
      Sekunden + (PeekB(lBuffer+1)&$FF) << 16
      Sekunden + (PeekB(lBuffer+2)&$FF) << 8
      Sekunden + (PeekB(lBuffer+3)&$FF) 

      
      
      
      Debug StrQ(Sekunden)

     
      Debug ("Zeit vom Server empfangen!")
      Quit = 1
    EndIf
    If ClientEvent  = 0 ;Keine Reaktion vom Zeit-Server
      TimeOutConter =  TimeOutConter + 1
      If TimeOutConter > ServerTimeOut
        MessageRequester("ZeitServerTimeOut", "Der Zeitserver übermittelt keine Zeitinformationen!", 0)
        Quit = 1
      EndIf
    EndIf
  Until Quit = 1

CloseNetworkConnection(ConnectionID)
End 
Hat jemand eine Idee oder einen Tip oder einen Link, wie ich diesen Wert weiterverarbeiten muss?
Habe mich noch nie wirklich mit dem Auslesen einzelner Bytes oder Bits beschäftigt, vor allem ist mir völlig unklar, wie ich den Ganzahligen Anteil mit dem Nachkommateil zusammensetzen kann, wobei mir eigtl, der ganzahlige Anteil, der wohl die Anzahl der Sekunden seid 1.1.1900 darstellt, vollkommen reichen würde.

Verfasst: 21.09.2007 16:34
von mk-soft

Verfasst: 21.09.2007 17:41
von Unimatrix Zero
Hallo mk-soft,

erst mal vielen Dank für den Link, leider klappt das damit auch nicht, hatte ich aber auch schon ausprobiert.
Irgendwie scheint es da einen Unterschied zu geben zwischen dem 32 Bit Wert über den Port 37 via TCP/IP mit dem Time Protokoll und dem 64 Bit Wert über den Port 123 via UDP und dem NTP Protokoll.
Vielleicht ist aber auch der Befehl "/n" schon falsch, aber ich bekomme als Ergebnis jedenfalls 8 zurückgemeldet und gehe eigtl. davon aus, dass dann in den 8 Bytes auch der Timestamp enthalten ist.
Habe mir das mal wieder wesentlicher einfacher vorgestellt, spiele aber jetzt schon seid Stunden damit ohne Ergebnis rum :(

Verfasst: 21.09.2007 19:32
von Unimatrix Zero
Hallo zusammen,

bin im IN jetzt noch auf eine ganz andere Lösung gestossen, NetRemoteTod heißt das Zauberwort bzw. die API-Funktion.
Ist natürlich bestimmt nicht die beste Lösung und ich weiß auch noch nicht ob das von jedem Client aus funktionieren wird.
Für jeden den es interessiert (muss übrigens mit Unicodeunterstützung compiliert werden):

Code: Alles auswählen

 Structure TIME_OF_DAY_INFO
    tod_elapsedt.l
    tod_msecs.l
    tod_hours.l
    tod_mins.l
    tod_secs.l
    tod_hunds.l
    tod_timezone.l
    tod_tinterval.l
    tod_day.l
    tod_month.l
    tod_year.l
    tod_weekday.l
EndStructure


Procedure.l GetRemoteDateTime(Server.s)
  TODI.TIME_OF_DAY_INFO
  Buffer.l
  retval.l = NetRemoteTOD_(Server, @Buffer)
  If retval = 0 
    CopyMemory_(TODI, Buffer, SizeOf(TODI))
    DateTime.l = Date(TODI\tod_year,TODI\tod_month,TODI\tod_day,TODI\tod_hours,TODI\tod_mins,TODI\tod_secs)
    DateTime = AddDate(DateTime,#PB_Date_Minute,TODI\tod_timezone * -1)
    ProcedureReturn  DateTime
  EndIf
EndProcedure

Server.s = "Zeitserver"
DateTime.l = GetRemoteDateTime(server)
Debug FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", DateTime)
Trotzdem wäre ich natürlich an der schickeren Lösung mit NTP weiterhin interessiert, vor allem nachdem ich da jetzt schon so viel Zeit reingesteckt habe will ich noch nicht so schnell aufgeben.