Ke kākau ʻana i kahi mea kūʻai maʻalahi NTP

Aloha poʻe habrauser. 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. Ma ke kumu, e huli ke kamaʻilio ʻana i ke ʻano o ka ʻeke a pehea e hana ʻia ai ka pane mai ka server NTP. E kākau ʻia ke code ma python, no ka mea, i koʻu manaʻo, ʻaʻohe ʻōlelo maikaʻi aʻe no ia mau mea. E hoʻolohe ka poʻe connoisseurs i ka like o ke code me ka code ntplib - ua "hoʻoulu ʻia" wau e ia.

No laila he aha ka NTP? ʻO NTP kahi protocol no ke kamaʻilio ʻana me nā kikowaena manawa. Hoʻohana ʻia kēia protocol i nā mīkini hou. No ka laʻana, ka lawelawe w32tm ma windows.

Aia he 5 mau mana o ka protocol NTP i ka huina. ʻO ka mua, manaʻo 0 (1985, RFC958) i kēia manawa i manaʻo ʻia he kahiko. Hoʻohana ʻia nā mea hou i kēia manawa, 1st (1988, RFC1059), 2nd (1989, RFC1119), 3rd (1992, RFC1305) a me 4th (1996, RFC2030). Hoʻohālikelike nā ʻano 1-4 me kekahi, ʻokoʻa wale lākou i nā algorithm o nā kikowaena.

Hōʻuluʻulu Pāke

Ke kākau ʻana i kahi mea kūʻai maʻalahi NTP

Hōʻailona lele (hōʻailona hoʻoponopono) he helu e hōʻike ana i ka ʻōlelo aʻo lua. ʻO ke ʻano:

  • 0 - ʻaʻohe hoʻoponopono
  • 1 - ka minuke hope o ka lā he 61 kekona
  • 2 - ʻo ka minuke hope o ka lā he 59 kekona
  • 3 - hāʻule ka server (ka manawa pau ʻole)

Helu mana (helu helu) – helu mana o ka protocol NTP (1-4).

ano (mode) - ke ʻano hana o ka mea hoʻouna packet. Waiwai mai ka 0 a i ka 7, ka mea maʻamau:

  • 3 - mea kūʻai
  • 4 - kikowaena
  • 5 - ke ʻano hoʻolaha

stratus (layering level) - 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 ke kikowaena me ka pae 1, etc.).
Pool he helu helu i kau inoa ʻia 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 kekona.
lohi aʻa (server latency) ʻo ia ka manawa e hiki ai ka uaki i ke kikowaena NTP, ma ke ʻano he helu mau kekona.
hoʻopuehu aʻa (server scatter) - ʻO ka hoʻopuehu ʻana o ka uaki kikowaena NTP ma ke ʻano he helu paʻa mau kekona.
Ref id (source id) – kiaʻi id. Inā he stratum 1 ka kikowaena, a laila ʻo ref id ka inoa o ka uaki atomic (4 mau huaʻōlelo ASCII). Inā hoʻohana ke kikowaena i kahi kikowaena ʻē aʻe, aia i ka ref id ka helu o kēia kikowaena.
Hōʻike nā māla hope 4 i ka manawa - 32 bits - ka ʻāpana integer, 32 bits - ka hapa hakina.
Reference - ka uaki 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 i loaʻa ai 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 e noʻonoʻo ʻia nā kahua hope ʻelua.

E kākau kāua 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

No ka hoʻouna ʻana (a loaʻa) i kahi ʻeke i ke kikowaena, pono mākou e hoʻololi iā ia i ʻāpana o nā bytes.
No kēia hana (a hoʻohuli), e kākau mākou i ʻelua mau hana - pack() a unpack ():

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

wehe i ka hana

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, ma ke ʻano he noi - code e hoʻohuli i ka pūʻolo i kahi kaula nani

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 pūʻolo i ke kikowaena

E hoʻouna i 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 kekona mai Ianuali 1, 1900), mana - kekahi o 1-4, mode - 3 (cond client).

Ua loaʻa i ke kikowaena ka noi, hoʻopiha i nā kahua āpau i ka ʻeke NTP, ke kope ʻana i ke kahua Hoʻomaka waiwai mai ke hoʻouna i, i hele mai i loko o ke noi. He mea pohihihi ia iaʻu no ke aha e hiki ʻole ai i ka mea kūʻai ke hoʻopiha koke i ka waiwai o kona 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 i ke kikowaena ke noi (E loaʻa), ka manawa i hoʻouna ai ke kikowaena i ka pane (ke hoʻouna i) a me ka manawa o ka loaʻa ʻana o ka pane a ka mea kūʻai aku - E holo (ʻaʻole i loko o ka pūʻolo). Me kēia mau waiwai hiki iā mākou ke hoʻonohonoho i ka manawa kūpono.

Ka hoʻouna ʻana a me ka loaʻa ʻana o ke code

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

ʻIkepili ʻikepili mai ke kikowaena

ʻO ka hana ʻana o ka ʻikepili mai ke kikowaena ua like ia me nā hana a ke keonimana Pelekane mai ka pilikia kahiko o Raymond M. Smallian (1978): "ʻAʻole i loaʻa i kahi kanaka kahi wati, akā aia kahi uaki pā pololei ma ka home, ʻo ia kāna. poina i kekahi manawa i ka makani. I kekahi lā, poina ʻo ia i ka hoʻomaka hou ʻana i ka uaki, hele ʻo ia e kipa i kona hoa, hoʻomoe me ia i ke ahiahi, a i kona hoʻi ʻana i ka hale, ua hoʻonohonoho pono ʻo ia i ka uaki. Pehea ʻo ia e hana ai inā ʻaʻole i ʻike mua ʻia ka manawa huakaʻi? ʻO ka pane: “I ka haʻalele ʻana i ka hale, hoʻomaka ke kanaka i ka uaki a hoʻomanaʻo i ke kūlana o nā lima. Ke hele mai nei i kahi hoaaloha a haʻalele i nā malihini, ʻike ʻo ia i ka manawa o kona hiki ʻana a haʻalele. Hiki iā ia ke ʻike i ka lōʻihi o kona hele ʻana. Ke hoʻi nei i ka home a nānā i ka uaki, hoʻoholo ke kanaka i ka lōʻihi o kona haʻalele ʻana. I ka unuhi ʻana mai kēia manawa i ka manawa āna i kipa ai, ʻike ke kanaka i ka manawa i hala ma ke alanui ma laila a hoʻi. Ma ka hoʻohui ʻana i ka hapalua o ka manawa ma ke alanui i ka manawa o ka haʻalele ʻana i nā malihini, loaʻa iā ia ka manawa e ʻike ai i ka manawa o ka hōʻea ʻana i ka home a hoʻoponopono i nā lima o kāna uaki e like me ia.

E huli i ka manawa e hana ana ke kikowaena ma ka noi:

  1. Ke ʻimi nei i ka manawa huakaʻi packet mai ka mea kūʻai aku i ke kikowaena: ((Hele mai - Kumu) - (Hoʻouna - Loaʻa)) / 2
  2. E ʻike 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 i loaʻa i ka manawa kūloko a hauʻoli i ke ola.

Hua Hua

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 loulou.

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka