simple SNTP python script

Here is the working script from the Second Edition of Python Network Programming Cookbook:

import socket, struct, sys, time

NTP_SERVER = '0.uk.pool.ntp.org'
TIME1970 = 2208988800

def sntp_client():
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    data = '\x1b' + 47 * '\0'
    client.sendto(data.encode('utf-8'), (NTP_SERVER, 123))
    data, address = client.recvfrom(1024)
    if data: print('Response received from:', address)
    t = struct.unpack('!12I', data)[10] - TIME1970
    print('\tTime = %s' % time.ctime(t))

if __name__ == '__main__':
    sntp_client()

It should be noted that the accepted answer neglects the fraction part of the timestamp, see e.g. IETF RFC5905, p.13. A code snippet including it could look like

import socket
import struct
import datetime

NTP_SERVER = '0.uk.pool.ntp.org'
NTP_DELTA = 2208988800 # given as system epoch (e.g. 1970-1-1) minus NTP epoch (1900-1-1) in [s]

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client:
    data = '\x1b' + 47 * '\0'
    client.sendto(data.encode('utf-8'), (NTP_SERVER, 123))
    data, _ = client.recvfrom(256)
    tx_s, tx_f = struct.unpack('!12I', data)[10:12] # seconds and fractional seconds
    tx_timestamp = (tx_s + float(tx_f)/2**32) - NTP_DELTA

print(datetime.datetime.fromtimestamp(tx_timestamp, datetime.timezone.utc)) 
# e.g.
# 2019-12-18 13:02:14.029521+00:00 # Note: UTC used here for output!

Also keep in mind that this only returns the transmit timestamp (tx; time when the server sent the packet). If you look for the milliseconds, the round trip delay might be signficant (see e.g. p.29 of the linked RFC5905).

Sidenote: the socket docs recommend to open the socket in a with context so that it is closed properly when not needed anymore.

Tags:

Python