[英]simple SNTP python script
我需要幫助來完成以下腳本:
import socket
import struct
import sys
import time
NTP_SERVER = '0.uk.pool.ntp.org'
TIME1970 = 2208988800L
def sntp_client():
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
data = str.encode('\xlb' + 47 * '\0')
client.sendto(data, (NTP_SERVER, 123))
data, addr = client.recvfrom(1024)
if data:
print('Response received from:', addr)
t = struct.unpack('!12I', data)[10]
t -= TIME1970
print('\tTime: %s' % time.ctime(t))
if __name__ == '__main__':
sntp_client()
預期輸出:
Response received from: ('80.82.244.120', 123)
Time: Tue Sep 13 14:49:38 2016
問題是程序沒有給出任何輸出。 看起來它卡在:
data, addr = client.recvfrom(1024)
我希望有人能幫我解決這個問題。
這是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()
應該注意的是,接受的答案忽略了時間戳的小數部分,例如參見IETF RFC5905 ,p.13。 包含它的代碼片段可能看起來像
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!
還要記住,這僅返回傳輸時間戳(tx;服務器發送數據包的時間)。 如果您尋找毫秒,則往返延遲可能很重要(請參閱鏈接的 RFC5905 的 egp29)。
旁注:套接字文檔建議在with
上下文中打開套接字,以便在不再需要時正確關閉它。
您編寫的腳本沒有任何問題,您需要尋找服務器可能不響應您的另一個原因,例如防火牆設置。 我自己的python SNTP腳本幾乎完全一樣:
#!/bin/env python
import socket
import struct
import sys
import time
TIME1970 = 2208988800L # Thanks to F.Lundh
pow2_31 = pow(2,31)
pow2_32 = pow(2,32)
pow2_16 = pow(2,16)
if len(sys.argv) < 2:
sys.stderr.write("Usage : " + sys.argv[0] + " <SNTP server>")
exit(1)
server = sys.argv[1]
client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
data = '\x1b' + 47 * '\0'
time_start = time.time()
try:
client.sendto( data, ( server, 123 ))
client.settimeout(2)
except:
print "server <%s> not recognized" % (server)
exit(2)
try:
data, address = client.recvfrom( 1024 )
except socket.timeout:
print "timed out"
exit(3)
if data:
time_reply = (time.time() - time_start) * 1000
print 'received %d bytes from %s in %d ms :' % (len(data), address, time_reply)
upacket = struct.unpack( '!48B', data )
print upacket
用法:
$ ./sntp_client.py 0.uk.pool.ntp.org
received 48 bytes from ('83.170.75.28', 123) in 154 ms :
(28, 3, 3, 236, 0, 0, 1, 171, 0, 0, 3, 0, 20, 139, 208, 232, 219, 177, 86, 148, 230, 192, 1, 15, 0, 0, 0, 0, 0, 0, 0, 0, 219, 177, 88, 27, 60, 214, 85, 212, 219, 177, 88, 27, 60, 238, 157, 39)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.