18
votes

I've written a ntp client in python to query a time server and display the time and the program executes but does not give me any results. I'm using python's 2.7.3 integrated development environment and my OS is Windows 7. Here is the code:

# File: Ntpclient.py
from socket import AF_INET, SOCK_DGRAM
import sys
import socket
import struct, time

# # Set the socket parameters 

host = "pool.ntp.org"
port = 123
buf = 1024
address = (host,port)
msg = 'time'


# reference time (in seconds since 1900-01-01 00:00:00)
TIME1970 = 2208988800L # 1970-01-01 00:00:00

# connect to server
client = socket.socket( AF_INET, SOCK_DGRAM)
client.sendto(msg, address)
msg, address = client.recvfrom( buf )

t = struct.unpack( "!12I", data )[10]
t -= TIME1970
print "\tTime=%s" % time.ctime(t)
5
Why don't you use ntplib? pypi.python.org/pypi/ntplib - Maksym Polshcha

5 Answers

25
votes

Use ntplib:

The following should work on both Python 2 and 3:

import ntplib
from time import ctime
c = ntplib.NTPClient()
response = c.request('pool.ntp.org')
print(ctime(response.tx_time))

Output:

Fri Jul 28 01:30:53 2017
17
votes

Here is a fix for the above solution, which adds fractions of seconds to the implementation and closes the socket properly. As it's actually just a handful lines of code, I didn't want to add another dependency to my project, though ntplib admittedly is probably the way to go in most cases.

#!/usr/bin/env python
from contextlib import closing
from socket import socket, AF_INET, SOCK_DGRAM
import struct
import time

NTP_PACKET_FORMAT = "!12I"
NTP_DELTA = 2208988800  # 1970-01-01 00:00:00
NTP_QUERY = b'\x1b' + 47 * b'\0'  

def ntp_time(host="pool.ntp.org", port=123):
    with closing(socket( AF_INET, SOCK_DGRAM)) as s:
        s.sendto(NTP_QUERY, (host, port))
        msg, address = s.recvfrom(1024)
    unpacked = struct.unpack(NTP_PACKET_FORMAT,
                   msg[0:struct.calcsize(NTP_PACKET_FORMAT)])
    return unpacked[10] + float(unpacked[11]) / 2**32 - NTP_DELTA


if __name__ == "__main__":
    print time.ctime(ntp_time()).replace("  ", " ")
4
votes

It should be

msg = '\x1b' + 47 * '\0' 

Instead of

msg = 'time'

But as Maksym said you should use ntplib instead.

0
votes
msg = '\x1b' + 47 * '\0'
.......
t = struct.unpack( "!12I", msg )[10]
0
votes

Sorry if my answer doesn't satisfy your expectations. I think it makes sense to use an existing solution. ntplib is a quite good library for working with NTP servers.