Kunyora mutengi ari nyore weNTP

Hello habrausers. Nhasi ndinoda kutaura nezve manyorero ako akareruka NTP mutengi. Chaizvoizvo, hurukuro ichatendeukira kune chimiro chepaketi uye kuti mhinduro kubva kuNTP server inogadziriswa sei. Iyo kodhi ichanyorwa mu python, nekuti, mumaonero angu, hapana mutauro uri nani wezvinhu zvakadaro. Connoisseurs vanozoteerera kune kufanana kwekodhi ine ntplib kodhi - ini "ndakafuridzirwa" nazvo.

Saka chii chinonzi NTP zvakadaro? NTP iprotocol yekutaurirana nemaseva enguva. Iyi protocol inoshandiswa mumichina yakawanda yemazuva ano. Semuenzaniso, iyo w32tm sevhisi pamahwindo.

Kune 5 shanduro dzeNTP protocol zvakazara. Yekutanga, vhezheni 0 (1985, RFC958) parizvino inonzi isingachashandi. Zvitsva zviri kushandiswa parizvino, 1st (1988, RFC1059), 2nd (1989, RFC1119), 3rd (1992, RFC1305) uye 4th (1996, RFC2030). Mavhezheni 1-4 anowirirana, anosiyana chete mune algorithms emaseva.

Packet Format

Kunyora mutengi ari nyore weNTP

Leap indicator (correction indicator) inhamba inoratidza kusvetuka yambiro yechipiri. Zvinoreva:

  • 0 - hapana kururamisa
  • 1 - miniti yekupedzisira yezuva ine 61 masekondi
  • 2 - miniti yekupedzisira yezuva ine 59 masekondi
  • 3 - server kukundikana (nguva kunze kwekuenderana)

Shanduro nhamba (nhamba yeshanduro) - NTP protocol vhezheni nhamba (1-4).

fashoni (modhi) - maitiro ekushanda emutumi wepakiti. Kukosha kubva pa0 kusvika ku7, zvakanyanya:

  • 3 - mutengi
  • 4 - server
  • 5 - nhepfenyuro mode

stratus (Layer level) - nhamba yezvikamu zvepakati pakati pevhavha newachi yereferensi (1 - sevha inotora data zvakananga kubva pawachi yereferensi, 2 - sevha inotora data kubva kuvhavha ine nhanho 1, nezvimwewo).
dziva i nhamba yakasainwa inomiririra nguva huru pakati pemeseji dzinotevedzana. Mutengi weNTP anotsanangura pano nguva yainotarisira kuvhota sevha, uye sevha yeNTP inotsanangura nguva yainotarisira kuvhoterwa. Kukosha kwakaenzana nebhinari logarithm yemasekonzi.
zvakarurama (chaizvo) i nhamba yakasainwa inomiririra chokwadi chewachi yehurongwa. Kukosha kwakaenzana nebhinari logarithm yemasekonzi.
kunonoka kwemidzi (server latency) ndiyo nguva yainotora kuti wachi isvike paNTP server, senhamba yakatarwa yemasekonzi.
kupararira kwemidzi (Server scatter) - Kupararira kweNTP server wachi senhamba yakagadziriswa yemasekonzi.
Ref id (mabviro id) - tarisa id. Kana sevha iine stratum 1, ipapo ref id izita reatomic wachi (4 ASCII mavara). Kana sevha ikashandisa imwe sevha, ipapo ref id ine kero yeiyi server.
Minda mina yekupedzisira inomiririra nguva - 4 bits - chikamu chizere, 32 bits - chikamu chechikamu.
Reference -wachi yazvino pane server.
Kwakabva - nguva iyo pakiti yakatumirwa (yakazadzwa nevhavha - zvimwe pane iyo pazasi).
Gamuchira - nguva apo pakiti yakagamuchirwa nevhavha.
fambisa - nguva iyo pakiti yakatumirwa kubva kune server kune mutengi (yakazadzwa nemutengi, zvimwe pane iyo pazasi).

Minda miviri yekupedzisira haingatariswe.

Ngatinyorei pasuru yedu:

Package code

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

Kutumira (uye kugamuchira) pakiti kune sevha, tinofanira kukwanisa kuishandura kuita hurongwa hwemabhaiti.
Kune iyi (uye kudzosera) mashandiro, isu tichanyora maviri mabasa - pack () uye unpack ():

pack basa

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 basa

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

Kune vanhu vane usimbe, sekushandisa - kodhi inoshandura pasuru kuita tambo yakanaka

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)

Kutumira pasuru kune server

Tumira pakiti ine minda yakazara kune server mhando, fashoni ΠΈ fambisa. The fambisa iwe unofanirwa kutsanangura nguva iripo pamushini wemunharaunda (nhamba yemasekondi kubva muna Ndira 1, 1900), shanduro - chero ye1-4, modhi - 3 (mutengi maitiro).

Sevha, yagamuchira chikumbiro, inozadza minda yese muNTP packet, kukopa mumunda Kwakabva kukosha kubva fambisa, iyo yakauya mukukumbira. Icho chakavanzika kwandiri kuti sei mutengi asingakwanisi kuzadza kukosha kwenguva yake mumunda Kwakabva. Nekuda kweizvozvo, kana packet yadzoka, mutengi ane 4 nguva kukosha - nguva iyo chikumbiro chakatumirwa (Kwakabva), nguva iyo sevha yakagamuchira chikumbiro (Gamuchira), nguva iyo sevha yakatumira mhinduro (fambisa) uye nguva yekugamuchira mhinduro nemutengi - Svika (kwete mupakeji). Nezvinokosha izvi tinogona kuseta nguva chaiyo.

Pakeji yekutumira uye kugamuchira kodhi

# 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)

Kugadziriswa kwedata kubva kuseva

Kugadziriswa kwedata kubva paseva kwakafanana nezvakaitwa nemuchinda wechiRungu kubva kudambudziko rekare raRaymond M. Smallian (1978): β€œMumwe munhu akange asina wristwatch, asi pamba paive newachi yemadziro, yaaive dzimwe nguva ndaikanganwa mhepo. Rimwe zuva, achikanganwa kutanga wachi zvakare, akaenda kunoshanyira shamwari yake, akapedza manheru naye, uye paakadzokera kumba, akakwanisa kuseta wachi zvakanaka. Akakwanisa sei kuita izvi kana nguva yekufamba yakanga isati yazivikanwa? Mhinduro yacho ndeiyi: β€œAchibuda mumba, munhu anosimudza wachi uye anoyeuka pakamira maoko. Kuuya kune shamwari uye kusiya vaenzi, anocherechedza nguva yekusvika kwake nekuenda. Izvi zvinomubvumira kuziva kuti akanga asipo kwenguva yakareba sei. Achidzokera kumba otarisa wachi, munhu anoona kuti achange asipo kwenguva yakareba sei. Achibvisa kubva panguva ino nguva yaakapedza achishanya, munhu wacho anowana nguva inopedzwa mumugwagwa ikoko nokudzoka. Nokuwedzera hafu yenguva yakashandiswa mumugwagwa kusvika panguva yekusiya vaenzi, anowana mukana wekuziva nguva yekusvika kumba uye kugadzirisa maoko ewachi yake zvakakodzera.

Tsvaga nguva iyo sevha yaishanda pachikumbiro:

  1. Kutsvaga iyo packet yekufamba nguva kubva kumutengi kuenda kune server: ((Kusvika - Kwekutanga) - (Tumira - Gamuchira)) / 2
  2. Tsvaga musiyano pakati pemutengi uye server nguva:
    Gamuchira - Mavambo - ((Svika - Mavambo) - (Tumira - Gamuchira)) / 2 =
    2 * Gamuchira - 2 * Mabviro - Svika + Origine + Tumira - Gamuchira =
    Gamuchira - Yekutanga - Svika + Tumira

Isu tinowedzera kukosha kwakagamuchirwa kunguva yeko uye tinonakidzwa nehupenyu.

Result Output

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)

Useful ссылка.

Source: www.habr.com

Voeg