Forum: Mikrocontroller und Digitale Elektronik ntp Server antwortet nicht


von dost0011 (Gast)


Lesenswert?

Hallo,

ich benutze den ESP8266. Wenn ich nun den NTP Server de.pool.ntp.org 
anfrage, bekomme ich keine Antwort "no packet yet". Was mache ich falsch 
oder ist der Server komplett überlastet?
1
// send an NTP request to the time server at the given address
2
unsigned long sendNTPpacket(IPAddress& address)
3
{
4
  Serial.println("sending NTP packet...");
5
  // set all bytes in the buffer to 0
6
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
7
  // Initialize values needed to form NTP request
8
  // (see URL above for details on the packets)
9
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
10
  packetBuffer[1] = 0;     // Stratum, or type of clock
11
  packetBuffer[2] = 6;     // Polling Interval
12
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
13
  // 8 bytes of zero for Root Delay & Root Dispersion
14
  packetBuffer[12]  = 49;
15
  packetBuffer[13]  = 0x4E;
16
  packetBuffer[14]  = 49;
17
  packetBuffer[15]  = 52;
18
19
  // all NTP fields have been given values, now
20
  // you can send a packet requesting a timestamp:
21
  udp.beginPacket(address, 123); //NTP requests are to port 123
22
  udp.write(packetBuffer, NTP_PACKET_SIZE);
23
  udp.endPacket();
24
}
25
26
unsigned long Get_NTP_Time()
27
{
28
  //get a random server from the pool
29
  WiFi.hostByName(ntpServerName, timeServerIP); 
30
31
  sendNTPpacket(timeServerIP); // send an NTP packet to a time server
32
  // wait to see if a reply is available
33
  delay(3000);
34
  
35
  int cb = udp.parsePacket();
36
  if (!cb) {
37
    Serial.println("no packet yet");
38
    return(0);
39
  }
40
  else {
41
    Serial.print("packet received, length=");
42
    Serial.println(cb);
43
    // We've received a packet, read the data from it
44
    udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
45
46
    //the timestamp starts at byte 40 of the received packet and is four bytes,
47
    // or two words, long. First, esxtract the two words:
48
49
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
50
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
51
    // combine the four bytes (two words) into a long integer
52
    // this is NTP time (seconds since Jan 1 1900):
53
    unsigned long secsSince1900 = highWord << 16 | lowWord;
54
55
    // now convert NTP time into everyday time:
56
     // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
57
    const unsigned long seventyYears = 2208988800UL;
58
    // subtract seventy years:
59
    unsigned long epoch = secsSince1900 - seventyYears;
60
    // print Unix time:
61
    Serial.print("NTP:");
62
    Serial.println(epoch);
63
    return(epoch); 
64
  }
65
}

[Mod: Code in C-Tags eingeschlossen]

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

dost0011 schrieb:
> Wenn ich nun den NTP Server de.pool.ntp.org anfrage, bekomme ich keine
> Antwort

Du machst ja auch kein NTP, sondern nur SNTP (Simple ...). Das kann 
keinen Pool nach der Zeit fragen, sondern nur einzelne Server.

Nimm gezielt einen NTP-Server und es sollte gehen.

von Maddin (Gast)


Lesenswert?

dost0011 schrieb:
1
>   delay(3000);

Das ist bestenfalls unschön. Pakete sollten verarbeitet werden, wenn sie 
ankommen.
1
>   int cb = udp.parsePacket();

Was macht denn diese Funktion und was gibt sie zurück?

Laß doch mal zum Testen einen lokalen Server laufen und schaue Dir an, 
was im Netzwerk passiert.

de.pool.ntp.org ist übrigens ein einzelner Server, wenn auch immer ein 
anderer.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

dost0011 schrieb:
> sendNTPpacket(timeServerIP); // send an NTP packet to a time server
>   // wait to see if a reply is available
>   delay(3000);
>
>   int cb = udp.parsePacket();

Das ist unschön. UDP ist ein verbindungsloses Protokoll. Du kannst keine 
unmittelbare Antwort erwarten. Diese kommt irgendwann... oder auch gar 
nicht.

Ich mache das beim ESP so, dass ich einmal den Request abfeuere und dann 
in loop() zyklisch frage, ob was über UDP reinkommt.
1
void
2
loop() 
3
{
4
    ... // some other stuff
5
    ntp_poll_time ();                
6
    ... // some other stuff
7
}

wobei:
1
void
2
ntp_poll_time (void)
3
{
4
    int packetsize;
5
6
    packetsize = ntp_udp.parsePacket();
7
8
    if (packetsize)
9
    {
10
        ntp_udp.read(ntp_packet_buffer, packetsize);                   // read packet
11
12
        if (packetsize == NTP_PACKET_SIZE)
13
        {
14
            unsigned long hi = word(ntp_packet_buffer[40], ntp_packet_buffer[41]);
15
            unsigned long lo = word(ntp_packet_buffer[42], ntp_packet_buffer[43]);
16
            unsigned long secsSince1900 = hi << 16 | lo;
17
18
            Serial.print ("TIME ");
19
            Serial.println(secsSince1900);
20
        }
21
        else
22
        {
23
            Serial.println("- wrong packet size");
24
        }
25
26
        Serial.flush ();
27
    }
28
}

Den kompletten Source findestg Du unter 
https://www.mikrocontroller.net/svnbrowser/wordclock24h/ESP8266/ESP-WordClock/

von dost0011 (Gast)


Lesenswert?

Also mit dem Delay habe ich rumgespielt, ob es besser oder schlechter 
wird. Spielt keine Rolle, ich kann es auch rausnehmen.
Es kommt einfach keine Antwort zurück - egal, ob ich warte oder nicht.
Kennt ihr das Phänomen?

von (prx) A. K. (prx)


Lesenswert?

Frank M. schrieb:
> Du machst ja auch kein NTP, sondern nur SNTP (Simple ...). Das kann
> keinen Pool nach der Zeit fragen, sondern nur einzelne Server.

Der DNS-Name de.pool.ntp.org liefert bei Übersetzung in eine IP-Adresse 
eine von mehreren Adressen und ist daher in Programmen, die DNS-Namen 
verstehen, üblicherweise direkt nutzbar. Oder hat die ESP-Lib spezielle 
Probleme damit?

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:
> Oder hat die ESP-Lib spezielle Probleme damit?

Ich hatte es damals beim ESP8266 mit de.pool.ntp.org und SNTP nicht 
hinbekommen. Ich hatte dann als Server 192.53.103.103 (ntp3.ptb.de) 
probiert. Das ging sofort. Deshalb habe ich es dann auf den Pool im 
Zusammenhang mit SNTP geschoben.

Eben habe ich es aber nochmal (unter Linux, habe gerade keinen ESP 
parat) mit einem SNTP-Client probiert:
1
$ sntp de.pool.ntp.org
2
sntp 4.2.8p11@1.3728-o (1)
3
2018-05-18 13:29:31.010213 (-0100) +0.000558 +/- 0.023336 de.pool.ntp.org 212.18.3.19 s2 no-leap

Das funktioniert. Kann sein, dass es damals ein anderes temporäres 
Problem gab. Ich nehme daher meine Behauptung zurück ;-)

Ich werde es heute abend aber trotzdem nochmal auf dem ESP ausprobieren.

: Bearbeitet durch Moderator
von dost0011 (Gast)


Lesenswert?

Ich habe jetzt mal einen festen Server (time.nist.gov NTP server) 
angefragt:

sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet
sending NTP packet...
129.6.15.28
no packet yet

Bin ratlos...

von dost0011 (Gast)


Lesenswert?

IPAddress timeServerIP(192,53,103,103);

funktioniert auch nicht. Liegt vermutlich nicht an den tausenden Servern 
sondern an meinem Code ;-)

Beitrag #5426364 wurde vom Autor gelöscht.
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

dost0011 schrieb:
> IPAddress timeServerIP(192,53,103,103);
>
> funktioniert auch nicht.

Dies wollte ich Dir gerade auch vorschlagen, hätte ja sein können, dass 
die Namensauflösung aus irgendeinem Grund nicht klappt. Obwohl, Du 
könntest Dir ja mal die IP-Adresse ausgeben lassen, die von 
WiFi.hostByName(ntpServerName, timeServerIP) ermittelt wird.

> Liegt vermutlich nicht an den tausenden Servern
> sondern an meinem Code ;-)

Den habe ich schon mit meinem Code

  https://www.mikrocontroller.net/svnbrowser/wordclock24h/ESP8266/ESP-WordClock/

verglichen. Ich kann keinen größeren Unterschied erkennen, bis auf das 
Delay. Wie gesagt: Schick das Paket einmal ab und führe den Aufruf von 
udp.parsePacket() & Co. zyklich in der Hauptschleife aus, ich hatte das 
oben schon so skizziert.

: Bearbeitet durch Moderator
von (prx) A. K. (prx)


Lesenswert?

Frank M. schrieb:
> Wie gesagt: Führe den Aufruf von udp.parsePacket() & Co. zyklich
> in der Hauptschleife aus, ich hatte das oben schon so skizziert.

Wobei der ESP eigentlich für ereignisorientiertes Arbeiten ausgelegt 
ist, nicht für sequentielles Arbeiten mit Warterei. Also nicht
   Anfrage senden
   warten
   Antwort auswerten
sondern
   Anfrage senden
und unabhängig davon
   Wenn ein UDP Paket eintrifft, dann
      Paket auswerten

Damit habe ich bessere Erfahrungen gemacht. Allerdings war das in LUA.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:
> Wobei der ESP eigentlich für ereignisorientiertes Arbeiten ausgelegt
> ist, nicht für sequentielles Arbeiten mit Warterei.

Dann passt das ja zu meinem Vorschlag.

von Michael U. (amiga)


Lesenswert?

Hallo,

nur am Rande: zu den ESP8266 Extensions, die Bestandteil des SDK sind, 
gehört auch die nahezu vollständige Implemetierung der Posix-Time-Lib.
1
#include <ESP8266WiFi.h>
2
#include <time.h>
3
4
setup()
5
{
6
// Start Time service.
7
  configTime(timezone * 3600, 0, "pool.ntp.org", "time.nist.gov");
8
}
9
10
Mit
11
  time_t now = time(nullptr);
12
  struct tm * timeinfo;
13
  timeinfo = localtime(&now);
14
füllt man z.B. die Struktur.
15
 Serial.printf("%02d:%02d:%02d",timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
16
  Serial.println();

Es läuft komplett asyncron im Hintergrund, aktualisiert wird per default 
alle Stunde.

Genaueres kann man sich z.B. hier raussuchen.
https://github.com/esp8266/Arduino/blob/master/tools/sdk/libc/xtensa-lx106-elf/include/time.h

Gruß aus Berlin
Michael

von foobar (Gast)


Lesenswert?

Und du bist dir sicher, dass die Pakete auch ins Internet gehen und die 
Antworten auch richtig weitergeleitet werden? Nicht dass ne Firewall 
oder fehlendes NAT dir dazwischenfunken ...

von fchk (Gast)


Lesenswert?

dost0011 schrieb:

>   packetBuffer[0] = 0b11100011;   // LI, Version, Mode

Das ist falsch. Lies den Standard RFC4330.

LI: Bit 7-6, hier 3 (unsynchronisiert), ok
Version: Bit 2-0, hier 3, auch nicht falsch. Ich würde hier Version 1 
nehmen.
Mode: Bit 5-3, hier 4, und das ist FALSCH.
Du musst hier als Client eine 3 reinschreiben, der Server muss mit 
Mode=4 antworten. Mode=5 ist für Broadcasts.

fchk

von oszi40 (Gast)


Lesenswert?

foobar schrieb:
> Nicht dass ne Firewall
> oder fehlendes NAT dir dazwischenfunken ...

Bevor man große Sprünge macht, sollte man sich in kleinen Schritten 
vergewisseren, daß die einfachen Sachen schon mal funktionieren?
Ping wird ausgeführt für de.pool.ntp.org [195.201.19.162] mit 32 Bytes 
Daten:
Antwort von 195.201.19.162: Bytes=32 Zeit=76ms TTL=53 usw.

Beitrag #5426617 wurde vom Autor gelöscht.
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

fchk schrieb:
> Du musst hier als Client eine 3 reinschreiben, der Server muss mit
> Mode=4 antworten. Mode=5 ist für Broadcasts.

Ich habe das mal unter Linux ausprobiert.

Sowohl
1
   packetBuffer[0] = 0b11100011;  // vom TO verwendet
als auch
1
   packetBuffer[0] = 0b00011011;  // findet man in diversen Quellen
2
                                  // LI = 0, NV = 3, MODE = 3

werden von us.pool.ntp.org, de.pool.ntp.org und ntp3.ptb.de ohne Mucken 
geschluckt. Offenbar interessiert sich keiner für die LI, NV und 
MODE-Bits. Naja, nicht ganz: bei packetBuffer[0] = 0x00 antwortet keiner 
mehr.

Ich habe sonst überhaupt keine Felder im Paket mehr gefüllt, also alles 
bei 0 gelassen (durch memset).

Verwendeter Source:

https://lettier.github.io/posts/2016-04-26-lets-make-a-ntp-client-in-c.html

: Bearbeitet durch Moderator
von dost0011 (Gast)


Lesenswert?

Ok, jetzt habe ich folgendes gemacht:
Bei den Arduino Beispiel Sketchen gibt es unter ESP8266Wifi-->NTPClient. 
Diesen Sketch habe ich auf den ESP8266 geladen. Er verbindet sich 
einwandfrei mit dem Internet und dann bekomme ich folgenden Output

sending NTP packet...
no packet yet
sending NTP packet...
packet received, length=48
Seconds since Jan 1 1900 = 3735663005
Unix time = 1526674205
The UTC time is 20:10:05
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet
sending NTP packet...
no packet yet

Das bedeutet, dass es einmal funktioniert hat und dann nicht mehr. Das 
reicht natürlich nicht. Wenn ich einen Reset mache, kann es sein, dass 
er für 10min (dann habe ich abgebrochen) kein einziges Paket empfangen 
habe...

Anpingen kann ich den Server vom Rechner aus.
Was ist da los? Kann mich erinnern, dass das vor einem Jahr sofort und 
zuverlässig funktioniert hat...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

dost0011 schrieb:
> Das bedeutet, dass es einmal funktioniert hat und dann nicht mehr.

Kann es sein, dass der Timeserver dicht macht, wenn Du ihn so zuknallst? 
Wie groß sind die zeitlichen Abstände?

von dost0011 (Gast)


Lesenswert?

alle 2s. Ich würde ja nicht knallen, wenn er mal antworten würde :-)

von Jim M. (turboj)


Lesenswert?

Warum nimmst Du nicht Deinen eigenen Server? Den ntpd gibts notfalls 
auch für Windows, und 'nen Wireshark kann man so auch gleich mit 
ansetzen.

von Stephan Dorenkamp (Gast)


Lesenswert?

Das Gerät, welches ich bauen möchte, kommt in einer Umgebung zum 
Einsatz, wo es keinen weiteren Rechner gibt. Kann doch nicht sein, dass 
man einen eigenen Zeitserver benötigt, weil die vorhandenen nicht 
antworten. Ich habe doch bestimmt ein ganzes anderes Problem...

von foobar (Gast)


Lesenswert?

Den lokalen Server benutzt du zum Testen und Debuggen. Wenn's lokal 
läuft, kannst du mit den öffentlichen weitermachen.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

foobar schrieb:
> Den lokalen Server benutzt du zum Testen und Debuggen.

Vor allem kannst Du dort problemlos einen Wireshark aktivieren oder 
tcpdump laufen lassen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.