ืฉืืื ืืคืืืขืื. ืืืื ืื ื ืจืืฆื ืืืืจ ืขื ืืื ืืืชืื ืืงืื NTP ืคืฉืื ืืฉืื. ืืขืฆื, ืืฉืืื ืชืคื ื ืืืื ื ืืืืืื ืืืืืคื ืขืืืื ืืชืืืื ืืฉืจืช ื-NTP. ืืงืื ืืืืชื ื-python, ืื ืืืขืชื, ืคืฉืื ืืื ืฉืคื ืืืื ืืืชืจ ืืืืจืื ืืืื. ืื ืื ื ืืขื ืืฉืืื ืื ืืืืืื ืฉื ืืงืื ืขื ืงืื ntplib โ "ืฉืืืชื ืืฉืจืื" ืืื ื.
ืื ืื ืื ืืืื NTP? NTP ืืื ืคืจืืืืงืื ืืชืงืฉืืจืช ืขื ืฉืจืชื ืืื. ืคืจืืืืงืื ืื ืืฉืืฉ ืืืืื ืืช ืืืืจื ืืืช ืจืืืช. ืืืืืื, ืฉืืจืืช w32tm ืืืืื ืืช.
ืืฉื ื 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 ืืฆืืื ืืช ืืืจืืื ืฉืื ืืื ืืฆืคื ืืืืฉืื. ืืขืจื ืฉืืื ืืืืืจืืชื ืืืื ืืจื ืฉื ืฉื ืืืช.
ืืืืง (ืืืืง) ืืื ืืกืคืจ ืฉืื ืืกืืื ืืืืืฆื ืืช ืืืืืง ืฉื ืฉืขืื ืืืขืจืืช. ืืขืจื ืฉืืื ืืืืืจืืชื ืืืื ืืจื ืฉื ืฉื ืืืช.
ืขืืืื ืฉืืจืฉ (ืืฉืืืืช ืฉืจืช) ืืื ืืืื ืฉืืืงื ืืฉืขืื ืืืืืข ืืฉืจืช NTP, ืืืกืคืจ ืฉื ืืืช ืงืืืข.
ืคืืืืจ ืฉืืจืฉืื (ืคืืืืจ ืฉืจืช) - ืืคืืืืจ ืฉื ืฉืขืื ืฉืจืช NTP ืืืกืคืจ ืฉื ืืืช ืื ืงืืื ืงืืืขื.
ืชืขืืืช ืืืืช (ืืืื ืืงืืจ) - ืืืื ืฉืขืื. ืื ืืฉืจืช ืืฉ ืฉืืื 1, ืื ref id ืืื ืืฉื ืฉื ืืฉืขืื ืืืืืื (4 ืชืืื ASCII). ืื ืืฉืจืช ืืฉืชืืฉ ืืฉืจืช ืืืจ, ืืื ื-ref id ืืืื ืืช ืืืชืืืช ืฉื ืฉืจืช ืื.
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))
ืคืื ืงืฆืืืช unpack
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)
ืขืืืื ื ืชืื ืื ืืืฉืจืช
ืขืืืื ืื ืชืื ืื ืืืฉืจืช ืืืื ืืคืขืืืืชืื ืฉื ืื'ื ืืืื ืืื ืืื ืืืืขืื ืืืฉื ื ืฉื ืจืืืืื ื ื. ืกืืืืืื (1978): "ืืืื ืืื ืื ืืื ืฉืขืื ืื, ืืื ืืื ืฉืขืื ืงืืจ ืืืืืง ืืืืช, ืฉืืื ืืคืขืืื ืฉืืื ืืจืื. ืืื ืืื, ืืฉืฉืื ืืืคืขืื ืืช ืืฉืขืื ืฉืื, ืืื ืืืงืจ ืืช ืืืจื, ืืืื ืืืชื ืืช ืืขืจื, ืืืฉืืืจ ืืืืชื ืืฆืืื ืืืืื ืืช ืืฉืขืื ื ืืื. ืืื ืืื ืืฆืืื ืืขืฉืืช ืืืช ืื ืืื ืื ืกืืขื ืื ืืื ืืืืข ืืจืืฉ? ืืชืฉืืื ืืื: "ืืืฆืืื ืืืืืช, ืืื ืืขืื ืืช ืืฉืขืื ืืืืืจ ืืช ืืืงืื ืืืืืืื. ืืืืื ืืืืจ ืืืฉืืืจ ืืช ืืืืจืืื, ืืื ืืฆืืื ืืช ืฉืขืช ืืืขืชื ืืืฆืืืชื. ืื ืืืคืฉืจ ืื ืืืืืช ืืื ืืื ืืื ื ืขืืจ. ืืืืจ ืืืืชื ืืืกืชืื ืืฉืขืื, ืืื ืงืืืข ืืช ืืฉื ืืืขืืจืืชื. ืืืคืืชืช ืืื ืื ืืช ืืืื ืฉืืืื ืืืืงืืจ, ืืืื ืืืื ืืช ืืื ืืฉืืืช ืืืืืฉ ืืืื ืืฉืื. ืขื ืืื ืืืกืคืช ืืืฆืืช ืืืื ืืฉืืืื ืืืจืืื ืืืื ืืฉืืจืช ืืืืจืืื, ืืื ืืงืื ืืืืื ืืช ืืืจืจ ืืช ืฉืขืช ืืืืขื ืืืืชื ืืืืชืืื ืืช ืืืืื ืืฉืขืื ืฉืื ืืืชืื.
ืืฆื ืืช ืืืื ืฉืื ืืฉืจืช ืขืื ืขื ืืืงืฉื:
- ืืฆืืืช ืืื ืื ืกืืขื ืฉื ืื ืืช ืืืืงืื ืืฉืจืช: ((ืืืขื - ืืงืืจ) - (ืฉืืืืจ - ืงืืื)) / 2
- ืืฆื ืืช ืืืืื ืืื ืืื ืืืงืื ืืฉืจืช:
ืงืืื - ืืงืืจ - ((ืืืขื - ืืงืืจ) - (ืฉืืืืจ - ืงืืื)) / 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