αα½ααααΈβα’αααβααααΎβααααΆααα ααααααααααα»αα
αααα·ααΆαα’αααΈααααααααααααΆαααΈαααααα NTP ααΆααααααααΆαααααα½αααααα’αααα ααΆααΌαα
ααΆαααααααΆααΉααααααα
ααΆαα
ααΆαααααααααααααα
ααααααααΆα αα·ααααααααααΆαααααΎαααααΈαααΆαααΈααα NTP ααααΌαααΆαααααΎαααΆαα ααΌαααΉαααααΌαααΆααααααααΆ python αααααααΆααααα·ααααααααα»α ααΆαα·αααΆαααΆααΆααα’ααΆααααααΆααααΏαααααααααα Connoisseurs ααΉαααα
α·ααααα»αααΆααα
ααααααΆαααααααααααΆααααΌαααΆαα½ααααααΌα ntplib - αααα»αααααΌαααΆα "αααα»ααααα·α" αααααΆα
ααΌα
αααα NTP ααΆα’αααΈ? NTP ααΊααΆαα·ααΈααΆααααααΆααααααΆααααααααΆαα½ααααΆαααΈααααααααααΆα αα·ααΈααΆααααααααΌαααΆαααααΎαα
αααα»ααααΆαααΈαααααΎαααΆα
αααΎαα α§ααΆα ααα ααααΆ w32tm αα
ααΎ windows α
ααΆα 5 αααααααα·ααΈααΆα NTP ααα»αα ααΈαα½α αααα 0 (1985, RFC958) αα αα α»ααααααααααΌαααΆαα αΆαααα»αααΆαααααααΎα αΎαα ααααΈβααΆαβαααβααααΌαβααΆαβααααΎβααΆβαααβαα αα α»αααααα ααΈ 1 (1988, RFC1059), ααΈ 2 (1989, RFC1119), ααΈ 3 (1992, RFC1305) αα·αβααΈ 4 (1996, RFC2030) α αααα 1-4 ααΊααααΌαααααΆααΆαα½αααααΆαα αα·ααα αα αα½αααΆαα»αααααΆαααα αααα»ααααα½ααααααααΆααααααααΆαααΈαααααα»αααααα
αααααααααα αα
ααΌα
ααΆααααα (ααΌα
ααΆαααααααααΌα) ααΊααΆαααααααααα αΆαααΈααΆααααααΆαααΈααΈααααα α’ααααααα
- 0 - ααααΆαααΆααααααααΌα
- 1 - ααΆααΈα α»ααααααααααααααΆα 61 αα·ααΆααΈ
- 2 - ααΆααΈα α»ααααααααααααααΆα 59 αα·ααΆααΈ
- 3 - αααΆαααΈααααααΆααα (α’αααααααααΎααααΆααααα)
ααααααα (ααααααα) - ααααααααα·ααΈααΆα NTP (1-4) α
αααα (αααα) β ααααααααα·ααααα·ααΆαααααα’αααααααΎαααα ααααααααΆαα αααααααΈ 0 ααα 7 αααααΆααΏαααααααΆαααα»αα
- 3 - α’αα·αα·αα
- 4 - αααΆαααΈααα
- 5 - ααααααααΆα
αααααΆαα (ααααα·ααααααΆαα) - α
ααα½ααααααααΆααααααααααΆααααΆαααΈααα αα·αααΆα‘α·ααΆααα (1 - αααΆαααΈααααααα·αααααααααααααΆααααΈααΆα‘α·ααΆααα, 2 - αααΆαααΈααααααα·ααααααααΈαααΆαααΈααααααααΆαααααα·α 1 ααα)
α’αΆαα ααααΉα ααΊααΆα
ααα½αααααααααΆαα
α»αα αααααααΆααααΆαα±ααα
ααααααααα’αα·ααααΆαααΆαααΆαααΆααααααΆα αααΆαααΈαααααα NTP αααααΆαααα
ααΈαααα
αααααααααααααΆααααΉαααΆααΉαααααΎααΆααααααααα·ααΎαααΆαααΈααα α αΎααααΆαααΈααα NTP αααααΆααα
αααααααααααααΆααααΉαααΆααΉαααααΌαααΆαααααααααα αααααααΊααααΎααΉαααααΆααΈααααααΈααααα·ααΆααΈα
ααΆαααΆααααΆαα (ααΆαααΆααααΆαα) ααΊααΆα
ααα½αααααααααΆαα
α»αα αααααααΆααααΆαα±ααααΆαααααΉαααααΌαααααΆα‘α·ααΆααααααααα αααααααΊααααΎααΉαααααΆααΈααααααΈααααα·ααΆααΈα
ααΆααααααΆαααααΆ root (ααΆαααΊααααααααΆαααΈααα) ααΊααΆαααααααΆαααααΆααααΌαααΆααααααΆααααΆα‘α·ααΆααΎααααΈαα
ααααααΆαααΈααα NTP αααααΆα
ααα½αααααααα·ααΆααΈα
ααΆαααααααααααΆ root (ααα
αΆααααα
αΆααααΆαααΈααα) - ααΆαααα
αΆααααα
αΆαααααΆα‘α·ααΆαααΆαααΈααα NTP ααΆα
ααα½αα
ααα»α
ααααααα·ααΆααΈα
ααααααααΆααα―αααΆαααα (ααααααααΆααααααα) - ααΎαααααααααΆααα ααααα·αααΎαααΆαααΈαααααΆα stratum 1 ααα ref id ααΊααΆαααααααΆα‘α·ααΆα’αΆααΌαα·α (4 αα½α’αααα ASCII) α ααααα·αααΎαααΆαααΈαααααααΎαααΆαααΈααααααααααα αααααααααααΆαααααααΆαα’αΆααααααΆααααααααΆαααΈααααααα
ααΆα 4 α
α»ααααααααΊαααααααΆ - 32 αααΈα - αααααα
ααα½αααα 32 αααΈα - ααααααααααΆαα
α―αααΆαααα - ααΆα‘α·ααΆα
α»αααααααααα»ααα
ααΎαααΆαααΈαααα
ααΎαααααΎα - αααααααΆααααααα
ααααααααΆαααααΌαααΆαααααΎ (αααααααααααΆαααΈααα - ααααααααΎααΆααΆαααααα)α
ααα½αααΆα - αααααααΆααααααα
ααααααααΆαααααΌαααΆαααα½αααααααΆαααΈαααα
αααααΌα - αααααααΆααααααα
ααααααααΆαααααΌαααΆαααααΎααΈαααΆαααΈααααα
αααΆαααΈαααααα (ααααααααα’αα·αα·αα ααααααααΎαααααΆαααααα)α
ααΆαααΈαα α»ααααααααΉααα·αααααΌαααΆααα·α αΆαααΆααα
αααααααααααα ααααααααΎαα
αααααΌααααα αα
class NTPPacket:
_FORMAT = "!B B b b 11I"
def __init__(self, version_number=2, mode=3, transmit=0):
# Necessary of enter leap second (2 bits)
self.leap_indicator = 0
# Version of protocol (3 bits)
self.version_number = version_number
# Mode of sender (3 bits)
self.mode = mode
# The level of "layering" reading time (1 byte)
self.stratum = 0
# Interval between requests (1 byte)
self.pool = 0
# Precision (log2) (1 byte)
self.precision = 0
# Interval for the clock reach NTP server (4 bytes)
self.root_delay = 0
# Scatter the clock NTP-server (4 bytes)
self.root_dispersion = 0
# Indicator of clocks (4 bytes)
self.ref_id = 0
# Last update time on server (8 bytes)
self.reference = 0
# Time of sending packet from local machine (8 bytes)
self.originate = 0
# Time of receipt on server (8 bytes)
self.receive = 0
# Time of sending answer from server (8 bytes)
self.transmit = transmit
ααΎααααΈααααΎ (αα·αααα½α) αααα
ααααααααΆααα
αααΆαααΈααα ααΎαααααΌαααα’αΆα
ααααααααΆαααΆαα
ααΆα’αΆααααααα
αααααΆααααααα·ααααα·ααΆαααα (αα·ααααα
αααΆα) ααΎαααΉαααααααα»αααΆαααΈαααΊ pack() αα·α unpack():
αα»αααΆααααα αα
def pack(self):
return struct.pack(NTPPacket._FORMAT,
(self.leap_indicator << 6) +
(self.version_number << 3) + self.mode,
self.stratum,
self.pool,
self.precision,
int(self.root_delay) + get_fraction(self.root_delay, 16),
int(self.root_dispersion) +
get_fraction(self.root_dispersion, 16),
self.ref_id,
int(self.reference),
get_fraction(self.reference, 32),
int(self.originate),
get_fraction(self.originate, 32),
int(self.receive),
get_fraction(self.receive, 32),
int(self.transmit),
get_fraction(self.transmit, 32))
αα»αααΆααααααΆ
def unpack(self, data: bytes):
unpacked_data = struct.unpack(NTPPacket._FORMAT, data)
self.leap_indicator = unpacked_data[0] >> 6 # 2 bits
self.version_number = unpacked_data[0] >> 3 & 0b111 # 3 bits
self.mode = unpacked_data[0] & 0b111 # 3 bits
self.stratum = unpacked_data[1] # 1 byte
self.pool = unpacked_data[2] # 1 byte
self.precision = unpacked_data[3] # 1 byte
# 2 bytes | 2 bytes
self.root_delay = (unpacked_data[4] >> 16) +
(unpacked_data[4] & 0xFFFF) / 2 ** 16
# 2 bytes | 2 bytes
self.root_dispersion = (unpacked_data[5] >> 16) +
(unpacked_data[5] & 0xFFFF) / 2 ** 16
# 4 bytes
self.ref_id = str((unpacked_data[6] >> 24) & 0xFF) + " " +
str((unpacked_data[6] >> 16) & 0xFF) + " " +
str((unpacked_data[6] >> 8) & 0xFF) + " " +
str(unpacked_data[6] & 0xFF)
self.reference = unpacked_data[7] + unpacked_data[8] / 2 ** 32 # 8 bytes
self.originate = unpacked_data[9] + unpacked_data[10] / 2 ** 32 # 8 bytes
self.receive = unpacked_data[11] + unpacked_data[12] / 2 ** 32 # 8 bytes
self.transmit = unpacked_data[13] + unpacked_data[14] / 2 ** 32 # 8 bytes
return self
αααααΆααααα»ααααααα·αααΆαααααα·ααΈαα½α - ααΌαααααααααααα αααα ααΆααααα’αααααααααααααα’αΆα
def to_display(self):
return "Leap indicator: {0.leap_indicator}n"
"Version number: {0.version_number}n"
"Mode: {0.mode}n"
"Stratum: {0.stratum}n"
"Pool: {0.pool}n"
"Precision: {0.precision}n"
"Root delay: {0.root_delay}n"
"Root dispersion: {0.root_dispersion}n"
"Ref id: {0.ref_id}n"
"Reference: {0.reference}n"
"Originate: {0.originate}n"
"Receive: {0.receive}n"
"Transmit: {0.transmit}"
.format(self)
ααΆαααααΎαααα αααα αααΆαααΈααα
ααααΎαααα ααααααααΆααααααααααα αααΆαααΈααα αααα, αααα ΠΈ αααααΌαα ααα αααααΌα α’αααααααΌααααααααΆαααααααααΆαα αα α»αααααααα ααΎαααΆαααΈαααΌαααααΆα (α ααα½ααα·ααΆααΈα αΆααααΆααααΈααααααΈ 1 ααααααΆ ααααΆα 1900) αααα - ααΆαα½ααα 1-4 αααα - 3 (ααααα’αα·αα·αα) α
αααΆαααΈααα αααααΆαααα½αααααΎ ααααααααααααΆαααΆααα’αααααα»ααααα ααααααααΆα NTP αααα αααααα αααα»αααΆα ααΎαααααΎα αααααααΈ αααααΌααααααΆαα αΌααααααα»αααααΎα ααΆααΆα’αΆααααααΆαααααααΆαααααα»αααΆα ααα»α’αααΈααΆαααΆα’αα·αα·αααα·αα’αΆα αααααααααΆααααΌαααααααααααααααΆααααααΆαααα αααα»ααα·ααααααα ααΎαααααΎα. ααΆαααααααα αααααααααα ααααααααΆααααααααααα·α α’αα·αα·ααααΆαααααα 4 αα - αααααααΆαααααααΎααααΌαααΆαααααΎ (ααΎαααααΎα) αααααααΆααααααΆαααΈαααααΆαααα½αααααΎ (ααα½αααΆα) αααααααΆααααααΆαααΈαααααΆαααααΎααΆαααααΎααα (αααααΌα) αα·ααααααααΆααααΆαααα½αααΆαααααΎααααααα’αα·αα·αα - ααααα (αα·αααΆααα αααα»ααααα αα) α ααΆαα½αααΉααααααααΆαααααααΎαα’αΆα ααααααααααααΆααααΉαααααΌαα
ααΆαααααΎαα·αααα½ααααααΌααααα αα
# Time difference between 1970 and 1900, seconds
FORMAT_DIFF = (datetime.date(1970, 1, 1) - datetime.date(1900, 1, 1)).days * 24 * 3600
# Waiting time for recv (seconds)
WAITING_TIME = 5
server = "pool.ntp.org"
port = 123
packet = NTPPacket(version_number=2, mode=3, transmit=time.time() + FORMAT_DIFF)
answer = NTPPacket()
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.settimeout(WAITING_TIME)
s.sendto(packet.pack(), (server, port))
data = s.recv(48)
arrive_time = time.time() + FORMAT_DIFF
answer.unpack(data)
ααααΎαααΆααα·ααααααααΈαααΆαααΈααα
ααααΎαααΆααα·ααααααααΈαααΆαααΈαααααΊααααααααααΆαα ααΉααααααααΆααααααα»ααΆααα»ααααααΆαα·α’αααααααααΈαααα αΆα αΆαααααα Raymond M. Smallian (1978): "ααα»αααααααΆαααα·αααΆαααΆα‘α·ααΆαααα ααα»ααααααΆαααΆα‘α·ααΆαααααΆααααααΉαααααΌααα αααααααααΆαα αααααααααααα αααααα αααααα½ααααααααα α αΆααααααΎαααΆα‘α·ααΆααααααα ααΆααααΆααα ααααα·αααααααααΆαα α αααΆααααααααΆα ααΆαα½αααΆαα α αΎααααααΆαααααααααααααααα·α ααΆαααααα αααΆα‘α·ααΆααΆαααααΉαααααΌαα ααΎβααΆααβα αΆααα ααβααααΎβαααβαααβαααβααααβααΆ ααΎβαα·αβααΉαβαααβααααΎβααααΎαβαα»α? α αααΎαααΊα βα ααααΈαααα ααα»αααααααΆαααααααΆα‘α·ααΆ α αΎαα αα αΆαααΈααΆααααα αααααα·ααααααααα· α αΎαα αΆαα ααααΈααααα ααΆααααααααααΆαααααααααΆααααΆαααααα αα·αααΆαα αΆαα ααααααααΆααα αααα’αα»ααααΆαα±ααααΆααααΉαααΆααΆαααα ααααΆαααα»ααααΆαα αααααααααααααα·αα αΎαααΎαααΆα‘α·ααΆααα»αααααααΆαααααααααααααααααΆαα’ααααααΆαααααααΆααα ααβα ααβααΈβααααΆβαααβαααα½αβααΆαβαα βαα½αβαα»αβαα»ααα αα»ααααβαααβααβααΎαβααααΆβαααβα αααΆαβααΎβααααΌαβααΈβααα αα·αβαααα‘ααβααβαα·αα αααααααααααΆαααααααΆααααααααΆαααα αααΆαααΎααααΌααα ααΆαααααααααΆα αΆαα ααααΈααααα ααΆααααα½αααΆαα±ααΆαααΎααααΈαααααααααααααααααααα αα·ααααααααΌαααααΆα‘α·ααΆααααααΆααα±ααααααααα
ααααααααααααααΆααααααΆαααΈααααααα»αααααΎαααΆαααΎααααΎα
- ααααααααααααααΆααααΎααααΎααααααα ααααααααΆαααΈα’αα·αα·αααα αααΆαααΈαααα ((ααααα-ααΎα)-(αααααΌα-ααα½α))/α’
- αααααααααΆααα»αααααΆαααΆααααααααΆαααΆαααΈαααααα αα·ααααΆαααΈαααα
ααα½α-αααααααΎα-((ααααα-αααααααΎα)-(αααααΌα-ααα½α)) / 2 =
2 * ααα½α - 2 * αααααααΎα - ααααα + αααααααΎα + αααααΌα - ααα½α =
ααα½α - αααααααΎα - ααααα + αααααΌα
ααΎαααααααααααααααααα½αααΆααα αααααααα»ααααα»α α αΎαααΈαααΆαααΉαααΈαα·αα
αααααααααααα
time_different = answer.get_time_different(arrive_time)
result = "Time difference: {}nServer time: {}n{}".format(
time_different,
datetime.datetime.fromtimestamp(time.time() + time_different).strftime("%c"),
answer.to_display())
print(result)
ααΆααααααααα
ααααα: www.habr.com