Sawubona habrausers. Namuhla ngifuna ukukhuluma ngendlela yokubhala iklayenti lakho elilula le-NTP. Ngokuyisisekelo, ingxoxo izophendukela esakhiweni sephakethe nokuthi impendulo evela kuseva ye-NTP icutshungulwa kanjani. Ikhodi izobhalwa nge-python, ngoba, ngokubona kwami, alukho ulimi olungcono lwezinto ezinjalo. Ongoti bazonaka ukufana kwekhodi nekhodi ye-ntplib - "ngikhuthazwe" yiyo.
Manje yini i-NTP noma kunjalo? I-NTP iyiphrothokholi yokuxhumana namaseva esikhathi. Le protocol isetshenziswa emishinini eminingi yesimanje. Isibonelo, isevisi ye-w32tm kumawindi.
Kunezinguqulo ezi-5 zephrothokholi ye-NTP sezizonke. Eyokuqala, inguqulo engu-0 (1985, RFC958) okwamanje ibhekwa njengengasebenzi. Ezintsha zisetshenziswa njengamanje, 1st (1988, RFC1059), 2nd (1989, RFC1119), 3rd (1992, RFC1305) and 4th (1996, RFC2030). Izinguqulo 1-4 ziyahambisana, zihluka kuphela kuma-algorithms amaseva.
Ifomethi Yephakethe
Inkomba ye-Leap (inkomba yokulungisa) inombolo ekhombisa isixwayiso sesibili sokugxuma. Incazelo:
- 0 - akukho ukulungiswa
- 1 - umzuzu wokugcina wosuku uqukethe imizuzwana engama-61
- 2 - umzuzu wokugcina wosuku uqukethe imizuzwana engama-59
- 3 - ukwehluleka kweseva (isikhathi siphelelwe ukuvumelanisa)
Inombolo yenguqulo (inombolo yenguqulo) β inombolo yenguqulo yephrothokholi ye-NTP (1-4).
Mode (mode) β imodi yokusebenza yomthumeli wephakethe. Inani ukusuka ku-0 kuye ku-7, elivame kakhulu:
- 3 - iklayenti
- 4 - iseva
- 5 - imodi yokusakaza
Isigaxa (izinga lesendlalelo) - inani lezendlalelo eziphakathi phakathi kweseva newashi lereferensi (1 - iseva ithatha idatha ngokuqondile ewashi lereferensi, 2 - iseva ithatha idatha kusuka kuseva ngezinga 1, njll.).
ichibi iyinombolo esayiniwe emele umkhawulo wesikhawu phakathi kwemilayezo elandelanayo. Iklayenti le-NTP licacisa lapha isikhawu lapho lilindele ukuvotela iseva, futhi iseva ye-NTP icacisa isikhawu lapho ilindele ukuvota ngaso. Inani lilingana ne-logarithm kanambambili yamasekhondi.
Ukwenza kahle hle (ukunemba) iyinamba esayiniwe emelela ukunemba kwewashi lesistimu. Inani lilingana ne-logarithm kanambambili yamasekhondi.
ukubambezeleka kwezimpande (ukubambezeleka kweseva) isikhathi esisithathayo ukuze iwashi lifinyelele iseva ye-NTP, njengenombolo yephoyinti eligxilile lamasekhondi.
ukuhlakazeka kwezimpande (i-server scatter) - Ukuhlakazeka kwewashi leseva ye-NTP njengenombolo yephoyinti eligxilile lamasekhondi.
I-id yeref (i-id yomthombo) - i-id yokubuka. Uma iseva ine-stratum 1, i-ref id yigama lewashi le-athomu (izinhlamvu ezi-4 ASCII). Uma iseva isebenzisa enye iseva, i-id yeref iqukethe ikheli lale seva.
Izinkambu ezi-4 zokugcina zimelela isikhathi - amabhithi angu-32 - ingxenye ephelele, amabhithi angu-32 - ingxenye eyingxenye.
Izikhombo - iwashi lakamuva kuseva.
Isiqalo - isikhathi lapho iphakethe lithunyelwe (ligcwaliswe yiseva - okuningi kulokho okungezansi).
Thola β isikhathi lapho iphakethe lamukelwe khona yiseva.
Dlulisa - isikhathi lapho iphakethe lithunyelwe lisuka kuseva liya kuklayenti (ligcwaliswe iklayenti, okuningi kulokho okungezansi).
Izinkambu ezimbili zokugcina ngeke zicatshangelwe.
Masibhale iphakheji yethu:
Ikhodi yephakheji
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
Ukuthumela (nokwamukela) iphakethe kuseva, kufanele sikwazi ukuliguqula libe uchungechunge lwamabhayithi.
Kulokhu (kanye nokuhlehla) ukusebenza, sizobhala imisebenzi emibili - pack() futhi unpack():
umsebenzi wephakethe
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))
khipha umsebenzi
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
Kubantu abavilaphayo, njengohlelo lokusebenza - ikhodi eguqula iphakheji ibe yintambo enhle
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)
Ithumela iphakheji kuseva
Thumela iphakethe elinezinkambu ezigcwalisiwe kuseva Inguqulo, Mode ΠΈ Dlulisa. I Dlulisa kufanele ucacise isikhathi samanje emshinini wendawo (inombolo yemizuzwana kusukela ngoJanuwari 1, 1900), inguqulo - noma iyiphi ye-1-4, imodi - 3 (imodi yeklayenti).
Iseva, ngemva kokuthola isicelo, igcwalisa zonke izinkambu ephaketheni le-NTP, ikopishelwe ensimini Isiqalo inani kusuka Dlulisa, eyangena ngesicelo. Kuyimfihlakalo kimi ukuthi kungani iklayenti lingakwazi ukugcwalisa ngokushesha inani lesikhathi salo ensimini Isiqalo. Ngenxa yalokho, lapho iphakethe libuya, iklayenti linamanani wesikhathi esi-4 - isikhathi esithunyelwe ngaso isicelo (Isiqalo), isikhathi iseva ithole ngaso isicelo (Thola), isikhathi iseva ithumele ngaso impendulo (Dlulisa) kanye nesikhathi sokuthola impendulo yikhasimende - Fika (hhayi ephaketheni). Ngala magugu singakwazi ukusetha isikhathi esifanele.
Ikhodi yokuthumela nokwamukela iphakheji
# 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)
Ukucubungula idatha kusuka kuseva
Ukucutshungulwa kwedatha evela kuseva kufana nezenzo zomnumzane oyiNgisi ovela enkingeni endala kaRaymond M. Smallian (1978): βUmuntu oyedwa wayengenalo iwashi lesihlakala, kodwa kwakukhona iwashi lasodongeni elinembile ekhaya, alithola. ngezinye izikhathi ukhohlwe umoya. Ngolunye usuku, ekhohlwe ukuqala iwashi futhi, wavakashela umngane wakhe, wachitha ubusuku naye, futhi lapho ebuyela ekhaya, wakwazi ukusetha iwashi ngendlela efanele. Wakwazi kanjani ukwenza lokhu uma isikhathi sokuhamba sasingaziwa kusengaphambili? Impendulo ithi: βEphuma endlini, umuntu uvula iwashi abese ekhumbula ukuma kwezandla. Eza kumngane futhi eshiya izivakashi, uphawula isikhathi sokufika nokuhamba kwakhe. Lokhu kumenza akwazi ukuthola ukuthi ubehambe isikhathi esingakanani. Lapho ebuyela ekhaya futhi ebheka iwashi, umuntu unquma ukuthi ungekho isikhathi esingakanani. Esusa kulesi sikhathi isikhathi asichitha evakashile, umuntu uthola isikhathi asichitha emgwaqeni lapho futhi abuye. Ngokungeza ingxenye yesikhathi esichithwa emgwaqeni esikhathini sokushiya izivakashi, uthola ithuba lokuthola isikhathi sokufika ekhaya futhi alungise izandla zewashi lakhe ngokufanele.
Thola isikhathi iseva ibisebenza ngaso esicelweni:
- Ukuthola isikhathi sokuhamba kwephakethe kusuka kuklayenti kuya kuseva: ((Fika - Ivela) - (Dlulisa - Yamukela)) / 2
- Thola umehluko phakathi kwesikhathi seklayenti nesikhathi seseva:
Thola - Kwavela - ((Fika - Vele) - (Dlulisa - Yamukela)) / 2 =
2 * Thola - 2 * Kwavela - Fika + Kwavela + Thumela - Thola =
Yamukela - Okwangempela - Fika + Dlulisa
Sengeza inani elitholiwe esikhathini sendawo futhi sijabulele ukuphila.
Okukhipha Umphumela
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)
Iwusizo
Source: www.habr.com