Aloha, nā mea hoʻohana Habrahabr. I kēia lā makemake wau e kamaʻilio e pili ana i ke kākau ʻana i kāu mea kūʻai NTP maʻalahi. E uhi nui mākou i ka ʻōnaehana packet a pehea e hana ai i nā pane mai kahi kikowaena NTP. E kākau ʻia ke code ma Python, no ka mea, ke manaʻoʻiʻo nei au ʻaʻohe ʻōlelo maikaʻi aʻe no kēia ʻano mea. E ʻike ka poʻe kamaʻāina i ke kumuhana i ka like me ntplib—ua hoʻoikaika ʻia wau e ia.
No laila, he aha ka NTP? ʻO ka NTP kahi protocol no ka launa pū ʻana me nā kikowaena manawa pololei. Hoʻohana ʻia kēia protocol i nā mīkini hou. No ka laʻana, ʻo ka lawelawe w32tm ma windows.
Aia he 5 mau mana o ke kaʻina hana NTP. ʻO ka mea mua, ka mana 0 (1985, RFC958), ua manaʻo ʻia he mea kahiko i kēia manawa. Ke hoʻohana ʻia nei nā mana hou: ka mana 1 (1988, RFC1059), ka mana 2 (1989, RFC1119), ka mana 3 (1992, RFC1305), a me ka mana 4 (1996, RFC2030). Hoʻohālikelike ʻia nā mana 1-4 kekahi me kekahi; ʻokoʻa wale nō lākou i kā lākou algorithm hana. nā kikowaena.
ʻAno pūʻolo

Hōʻailona lele (hōʻailona hoʻoponopono) - he helu e hōʻike ana i ka lele lua o ka ʻōlelo aʻo. ʻO ke ʻano:
- 0 - ʻaʻohe hoʻoponopono
- 1 - ʻo ka minuke hope o ka lā he 61 kekona
- 2 - ʻo ka minuke hope o ka lā he 59 kekona
- 3 - ka hana hewa o ka server (ʻaʻole i hoʻonohonoho ʻia ka manawa)
Helu mana (helu helu) – helu mana o ka protocol NTP (1-4).
ano (mode) - ke ʻano hana o ka mea hoʻouna packet. Nā waiwai mai 0 a 7, ka mea maʻamau:
- 3 – mea kūʻai
- 4 – kikowaena
- 5 - ke ʻano hoʻolaha
stratus (pae pae) - ka helu o nā papa waena ma waena o ke kikowaena a me ka uaki kuhikuhi (1 - lawe pololei ke kikowaena i ka ʻikepili mai ka uaki kuhikuhi, 2 - lawe ke kikowaena i ka ʻikepili mai kahi kikowaena ma ka pae 1, etc.).
Pool — he integer pūlima e hōʻike ana i ka wā lōʻihi ma waena o nā memo. Hōʻike ka mea kūʻai NTP ma aneʻi i ka wā e manaʻo ai e koho i ke kikowaena, a ʻo ke kikowaena NTP e kuhikuhi i ka wā i manaʻo ʻia e koho ʻia. Ua like ka waiwai me ka logarithm binary o kekona.
Ke koho (ka pololei) — he integer pūlima e hōʻike ana i ka pololei o ka uaki ʻōnaehana. Ua like ka waiwai me ka logarithm binary o ka lua.
Hoʻopaneʻe aʻa (server latency) - ka manawa e pono ai no ka heluhelu ʻana i ka uaki e hiki i ka kikowaena NTP, ma ke ʻano he mau kekona paʻa.
Puka aʻa (ka hola hoʻolaha kikowaena) — Laha ʻia ka uaki kikowaena NTP ma ke ʻano he helu mau kekona paʻa.
Ref id (mea hōʻike kumu) - ka ID uaki. Inā loaʻa ka stratum 1 i ka server, a laila ʻo ka ref ID ka inoa o ka uaki atom (4 mau huaʻōlelo ASCII). Inā hoʻohana ke kikowaena i kahi kikowaena ʻē aʻe, a laila aia i ka ref ID ka helu o kēlā kikowaena.
ʻO nā mahina hope 4 e hōʻike ana i ka manawa - 32 bits - ʻāpana integer, 32 bits - hapa hapa.
Reference - nā heluhelu wati hou loa ma ke kikowaena.
Hoʻomaka - ka manawa i hoʻouna ʻia ai ka ʻeke (hoʻopiha ʻia e ke kikowaena - ʻoi aku ka nui ma lalo).
E loaʻa - ka manawa o ka loaʻa ʻana o ka ʻeke e ke kikowaena.
ke hoʻouna i - ka manawa i hoʻouna ʻia ai ka ʻeke mai ke kikowaena i ka mea kūʻai aku (hoʻopiha ʻia e ka mea kūʻai aku, ʻoi aku ka nui ma lalo).
ʻAʻole mākou e noʻonoʻo i nā kahua hope ʻelua.
E kākau i kā mākou pūʻolo:
Code pūʻolo
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
I mea e hoʻouna ai (a loaʻa) i kahi ʻeke i ke kikowaena, pono mākou e hoʻololi iā ia i kahi ʻano o nā bytes.
No kēia hana (a me ka hope), e kākau mākou i ʻelua mau hana - pack() a unpack ():
ʻO ka hana pūʻolo
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))
ʻO ka hana wehe
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
No ka poʻe palaualelo, eia kahi hoʻohui o ke code e hoʻololi i kahi ʻeke i kaula maikaʻi.
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)
Ka hoʻouna ʻana i kahi ʻeke i ke kikowaena
Pono e hoʻouna ʻia kahi ʻeke me nā kahua piha i ke kikowaena. Version, ano и ke hoʻouna i. ka ke hoʻouna i Pono ʻoe e kuhikuhi i ka manawa o kēia manawa ma ka mīkini kūloko (ka helu o nā kekona mai Ianuali 1, 1900), mana - kekahi o 1-4, mode - 3 (cond client).
Ua ʻae ka server, i ka ʻae ʻana i ka noi, hoʻopiha i nā kahua āpau i ka ʻeke NTP, e kope iā lākou i ke kula. Hoʻomaka manao mai ke hoʻouna i, i hiki mai i ka noi. He mea pohihihi ia iaʻu ke kumu hiki ʻole i ka mea kūʻai ke hoʻopiha koke i ko lākou manawa ma ke kula. Hoʻomaka. ʻO ka hopena, i ka wā e hoʻi mai ai ka ʻeke, loaʻa i ka mea kūʻai aku nā koina manawa 4 - ka manawa i hoʻouna ʻia ai ka noi (Hoʻomaka), ka manawa i loaʻa ai ka noi e ke kikowaena (E loaʻa), ka manawa i lawe ʻia e ke kikowaena e hoʻouna i kahi pane (ke hoʻouna i) a me ka manawa e loaʻa ai i ka mea kūʻai kahi pane - E holo (ʻaʻole i loko o ka pūʻolo). Ke hoʻohana nei i kēia mau waiwai, hiki iā mākou ke hoʻonohonoho i ka manawa kūpono.
Code no ka hoʻouna ʻana a me ka loaʻa ʻana o kahi ʻeke
# 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)
Hoʻoponopono ʻikepili mai ke kikowaena
Hoʻohālikelike ka hoʻoponopono ʻana i nā ʻikepili mai kahi kikowaena me nā hana a ke keonimana Pelekane i ka pilikia kahiko na Raymond M. Smullyan (1978): "ʻAʻohe wati lima o ke kanaka, akā he uaki pā pololei kāna ma ka home, poina iā ia i kekahi manawa i ka makani. ʻaʻole i ʻike mua ʻia?" ʻO ka pane: "I ka haʻalele ʻana i ka hale, ua hoʻohuli ke kanaka i kāna wati a hoʻomanaʻo i ke kūlana o nā lima. I ka hiki ʻana i kahi o kāna hoaaloha a haʻalele i ka pāʻina, ʻike ʻo ia i ka manawa o kona hiki ʻana mai a haʻalele. Ma ka hoʻohui ʻana i ka hapalua o ka manawa ma ke alanui i ka manawa i haʻalele ai i ka pāʻina, loaʻa iā ia ka manawa e ʻike ai i ka manawa o kona hōʻea ʻana i ka home a hoʻoponopono i nā lima o kāna wati e like me ia.
ʻIke mākou i ka manawa a ke kikowaena i hoʻohana ai i ka noi:
- ʻIke mākou i ka manawa huakaʻi o ka ʻeke mai ka mea kūʻai aku i ke kikowaena: ((Hele - Hoʻomaka) - (Hoʻouna - Loaʻa)) / 2
- ʻIke mākou i ka ʻokoʻa ma waena o ka mea kūʻai aku a me ka manawa kikowaena:
Loaʻa - Hoʻomaka - ((Hele - Hoʻomaka) - (Hoʻouna - Loaʻa)) / 2 =
2 * Loaʻa – 2 * Hoʻomaka – Hōʻea + Hoʻomaka + Hoʻouna - Loaʻa =
Loaʻa - Hoʻomaka - Hōʻea + Hoʻouna
Hoʻohui mākou i ka waiwai o ka hopena i ka manawa kūloko a hauʻoli i ke ola.
Puka o ka hopena
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)
Pono .
Source: www.habr.com
