Halo, Habrausers. An-diugh tha mi airson bruidhinn mu dheidhinn mar a sgrĂŹobhas tu an neach-dèiligidh NTP sĂŹmplidh agad fhèin. Gu bunaiteach, tionndaidh an còmhradh gu structar aâ phacaid agus an dòigh air am freagairt bhon fhrithealaiche NTP a ghiullachd. Thèid an còd a sgrĂŹobhadh ann am Python, oir tha e coltach riumsa nach eil dĂŹreach cĂ nan nas fheĂ rr airson rudan mar sin. Bheir connoisseurs fa-near cho coltach sa tha an còd leis aâ chòd ntplib - bha mi âair mo bhrosnachadhâ leis.
Mar sin dè a thâ ann an NTP co-dhiĂš? Tha NTP na phròtacal airson eadar-obrachadh le frithealaichean Ăšine cheart. Tha am protocol seo air a chleachdadh ann an iomadh inneal Ăšr-nodha. Mar eisimpleir, an t-seirbheis w32tm ann an uinneagan.
Tha 5 dreachan den phròtacal NTP ann gu h-iomlan. Thathas den bheachd gu bheil aâ chiad fhear, dreach 0 (1985, RFC958), seann-fhasanta an-drĂ sta. Tha dreachan nas Ăšire gan cleachdadh an-drĂ sta: dreach 1 (1988, RFC1059), dreach 2 (1989, RFC1119), dreach 3 (1992, RFC1305), agus dreach 4 (1996, RFC2030). Tha dreachan 1-4 co-chòrdail ri chèile; chan eil iad eadar-dhealaichte ach anns na h-algairim obrachaidh aca. frithealaichean.
Cruth pacaid

Comharra leum (comharra ceartachaidh) Ă ireamh a tha aâ comharrachadh an dĂ rna rabhadh leum. Ciall:
- 0 - chan eil ceartachadh ann
- 1 - tha 61 diogan anns a 'mhionaid mu dheireadh den latha
- 2 - tha 59 diogan anns aâ mhionaid mu dheireadh den latha
- 3 - fĂ iligeadh an fhrithealaiche (Ăšine a-mach Ă sioncranachadh)
Ăireamh an tionndaidh (Ă ireamh tionndaidh) - Ă ireamh dreach protocol NTP (1-4).
fasan (modh) - modh obrachaidh neach-cuiridh aâ phacaid. Luach bho 0 gu 7, as cumanta:
- 3 - neach-dèiligidh
- 4 - frithealaiche
- 5 - modh craolaidh
strath (ĂŹre còmhdachaidh) - an Ă ireamh de shreathan eadar-mheadhanach eadar an frithealaiche agus an gleoc iomraidh (1 - bidh am frithealaiche aâ toirt dĂ ta gu dĂŹreach bhon ghleoc iomraidh, 2 - bidh am frithealaiche aâ toirt dĂ ta bho fhrithealaiche le còmhdach 1, msaa).
Pool na shlĂ n-chunntas soidhnichte aâ riochdachadh an Ăšine as motha eadar teachdaireachdan leantainneach. Bidh an neach-dèiligidh NTP aâ sònrachadh an seo an eadar-ama aig a bheil dĂšil aige bhòtadh air an fhrithealaiche, agus tha am frithealaiche NTP aâ sònrachadh an eadar-ama aig a bheil dĂšil gun tèid a bhòtadh. Tha an luach co-ionann ris an logarithm binary de dhiog.
Precison (mion-chinnt) na shlĂ n-chunntas soidhnichte aâ riochdachadh cruinneas gleoc an t-siostaim. Tha an luach co-ionann ris an logarithm binary de dhiog.
Root dĂ il (dĂ il an fhrithealaiche) - an Ăšine a bheir e airson leughaidhean aâ ghleoc an t-seirbheisiche NTP a ruighinn, mar Ă ireamh puing stèidhichte de dhiog.
Sgaoileadh root (sgaoileadh frithealaiche) - sgaoileadh leughaidhean gleoc frithealaiche NTP mar grunn diogan le puing stèidhichte.
Ref id (stòr id) â faire id. Ma tha stratum 1 aig an fhrithealaiche, is e ref id ainm aâ ghleoc atamach (4 caractaran ASCII). Ma chleachdas am frithealaiche frithealaiche eile, bidh seòladh an fhrithealaiche seo anns an id ref.
Tha na 4 raointean mu dheireadh a 'riochdachadh na h-Ăšine - 32 pĂŹosan - am pĂ irt iomlan, 32 pĂŹosan - am pĂ irt bloighteach.
Fiosrachadh - an uaireadair as Ăšire air an fhrithealaiche.
TĂšs - Ă m nuair a chaidh am pasgan a chuir (air a lĂŹonadh a-steach leis an fhrithealaiche - barrachd air seo gu h-ĂŹosal).
Faigh - Ă m nuair a fhuair am frithealaiche am pasgan.
sgaoileadh - Ă m airson aâ phacaid a chuir bhon t-seirbheisiche chun neach-dèiligidh (air a lĂŹonadh a-steach leis an neach-dèiligidh, barrachd air seo gu h-ĂŹosal).
Cha tèid beachdachadh air an dà raon mu dheireadh.
SgrĂŹobhamaid ar pasgan:
Còd pacaid
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
Gus pasgan a chuir (agus fhaighinn) chun an fhrithealaiche, feumaidh sinn a bhith comasach air a thionndadh gu bhith na raon byte.
Airson an obrachaidh seo (agus air ais), sgrĂŹobhaidh sinn dĂ ghnĂŹomh - pasgan () agus dĂŹ-phapadh ():
gnĂŹomh pacaid
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))
gnĂŹomh 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
Do dhaoine leisg, mar thagradh - còd a thionndaidheas pasgan gu sreang bhrèagha
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)
A' cur pacaid dhan fhrithealaiche
Cuir pasgan le raointean lÏonta chun an fhrithealaiche tionndadh, fasan и sgaoileadh. Tha a ' sgaoileadh feumaidh tu an Úine là ithreach a shònrachadh air an inneal ionadail (an à ireamh de dhiog bho 1 Faoilleach 1900), dreach - gin de 1-4, modh - 3 (modh teachdaiche).
Bidh am frithealaiche, Ă s deidh dha an t-iarrtas fhaighinn, aâ lĂŹonadh a h-uile raon sa phasgan NTP, aâ dèanamh lethbhreac dhan raon TĂšs luach bho sgaoileadh, a thĂ inig anns an iarrtas. Tha e na dhĂŹomhaireachd dhomh carson nach urrainn don neach-dèiligidh luach a chuid Ăšine san raon a lĂŹonadh sa bhad TĂšs. Mar thoradh air an sin, nuair a thig am pasgan air ais, tha 4 luachan Ăšine aig an neach-dèiligidh - an Ăšine a chaidh an t-iarrtas a chuir (TĂšs), an Ăšine a fhuair am frithealaiche an t-iarrtas (Faigh), an Ăšine a chuir am frithealaiche am freagairt (sgaoileadh) agus an Ăšine a fhuair an neach-dèiligidh am freagairt - Thig (chan ann sa phacaid). Aâ cleachdadh nan luachan sin is urrainn dhuinn an Ăšine cheart a shuidheachadh.
Còd cur agus faighinn pacaid
# 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)
LĂ imhseachadh dĂ ta bhon fhrithealaiche
Tha lĂ imhseachadh dĂ ta bhon t-seirbheisiche coltach ri gnĂŹomhan an duine-uasal Sasannach bho sheann dhuilgheadas Raymond M. Smullyan (1978): âCha robh uaireadair aig aon fhear, ach bha gleoc balla ceart aig an taigh, a dhĂŹochuimhnich e uaireannan. a ghaoth. Aon latha, an dèidh dha dearmad a dhèanamh air an uaireadair aige a-rithist, chaidh e a chèilidh air a charaid, chuir e seachad am feasgar còmhla ris, agus nuair a thill e dhachaigh, chaidh aige air an uaireadair a shuidheachadh ceart. Ciamar a chaidh aige air seo a dhèanamh mura robh fios air an Ăšine siubhail ro-lĂ imh? Is e am freagairt: âNuair a dhâ fhĂ gas e an dachaigh, bidh neach a âtionndadh an uaireadair aige agus aâ cuimhneachadh dè an suidheachadh anns a bheil na lĂ mhan. An dèidh tighinn gu caraid agus na h-aoighean fhĂ gail, tha e a 'toirt fa-near an Ă m a thĂ inig e agus a dh' fhalbh e. Leigidh seo leis faighinn a-mach dè cho fada âs a bha e aâ tadhal. A 'tilleadh dhachaigh agus a' coimhead air a 'ghleoc, bidh neach a' dearbhadh fad a neo-lĂ thaireachd. Le bhith a 'toirt air falbh bhon Ă m seo an Ăšine a chuir e seachad a' tadhal, bidh neach a 'faighinn a-mach an Ăšine a thathar a' cur seachad a 'siubhal an sin agus air ais. Le bhith aâ cur leth na h-Ăšine a chaidh a chaitheamh air an rathad ris an Ă m a dhâ fhĂ g e na h-aoighean, gheibh e an cothrom faighinn a-mach an Ă m a rĂ inig e dhachaigh agus lĂ mhan an uaireadair aige atharrachadh a rèir sin.â
Lorg an Ăšine a bha am frithealaiche ag obair air an iarrtas:
- A 'lorg Úine siubhail a' phacaid bhon neach-dèiligidh chun an fhrithealaiche: ((Sig - Tòisich) - (Sguab às - Faigh)) / 2
- Lorg an diofar eadar Ă m teachdaiche agus frithealaiche:
Faigh - Tòisich - ((Thig - Tòisich) - (Gluasad - Faigh)) / 2 =
2 * Faigh - 2 * Tòiseachadh - Thig + Tòiseachadh + Tar-chuir - Faigh =
Faigh - TĂšs - Thig + Tar-chuir
Bidh sinn aâ cur an luach a thig Ă s a sin ris an Ă m ionadail agus aâ faighinn tlachd Ă beatha.
Toradh an toraidh
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)
Feumail .
Source: www.habr.com
