Kulemba kasitomala wa NTP wosavuta

Moni, Habrausers. Lero ndikufuna kulankhula za momwe mungalembere kasitomala wanu wosavuta wa NTP. Kwenikweni, zokambiranazo zitembenukira ku kapangidwe ka paketi ndi njira yosinthira yankho kuchokera ku seva ya NTP. Khodiyo idzalembedwa mu Python, chifukwa zikuwoneka kwa ine kuti palibe chilankhulo chabwinoko pazinthu zotere. Connoisseurs awona kufanana kwa code ndi ntplib code - "ndinadzozedwa" ndi izo.

Ndiye kodi NTP ndi chiyani kwenikweni? NTP ndi protocol yolumikizirana ndi ma seva anthawi yeniyeni. Protocol iyi imagwiritsidwa ntchito pamakina ambiri amakono. Mwachitsanzo, ntchito ya w32tm pawindo.

Pali mitundu 5 yonse ya protocol ya NTP. Yoyamba, mtundu 0 (1985, RFC958), pakadali pano ikuonedwa kuti ndi yakale. Mitundu yatsopano ikugwiritsidwa ntchito pakadali pano: mtundu 1 (1988, RFC1059), mtundu 2 (1989, RFC1119), mtundu 3 (1992, RFC1305), ndi mtundu 4 (1996, RFC2030). Mitundu 1-4 imagwirizana; imasiyana kokha mu ma algorithms awo ogwiritsira ntchito. maseva.

Mtundu wa paketi

Kulemba kasitomala wa NTP wosavuta

Leap chizindikiro (chizindikiro chowongolera) - nambala yomwe ikuwonetsa chenjezo la kugwirizanitsa kwachiwiri. Tanthauzo:

  • 0 - palibe kukonza
  • 1 - mphindi yomaliza ya tsiku ili ndi masekondi 61
  • 2 - mphindi yomaliza ya tsiku ili ndi masekondi 59
  • 3 - kusagwira ntchito kwa seva (nthawi sinalumikizidwe)

Nambala yamtundu (nambala ya mtundu) - Nambala ya mtundu wa protocol ya NTP (1-4).

mafashoni (mode) - njira yogwiritsira ntchito ya wotumiza paketi. Mtengo kuyambira 0 mpaka 7, wodziwika kwambiri:

  • 3 - kasitomala
  • 4 - seva
  • 5 - njira yowulutsira

Mzere (gawo laling'ono) - chiwerengero cha zigawo zapakati pakati pa seva ndi wotchi yowonetsera (1 - seva imatenga deta molunjika kuchokera ku wotchi yowonetsera, 2 - seva imatenga deta kuchokera ku seva ndi wosanjikiza 1, etc.).
Pool ndi nambala yosaina yomwe imayimira nthawi yayitali pakati pa mauthenga otsatizana. Makasitomala a NTP amatchula apa nthawi yomwe amayembekeza kusankha seva, ndipo seva ya NTP imatchula nthawi yomwe ikuyembekezeka kusankhidwa. Mtengo wake ndi wofanana ndi binary logarithm ya masekondi.
mwandondomeko (kulondola) ndi nambala yosainidwa yoyimira kulondola kwa wotchi yamakina. Mtengo wake ndi wofanana ndi binary logarithm ya masekondi.
Kuchedwa kwa mizu (kuchedwa kwa seva) - nthawi yomwe imatenga nthawi yowerengera mawotchi kuti ifike pa seva ya NTP, monga chiwerengero chokhazikika cha masekondi.
Kubalalika kwa mizu (kufalikira kwa seva) - kufalikira kwa mawotchi a seva ya NTP ngati masekondi angapo okhala ndi mfundo yokhazikika.
Ref id (chizindikiritso cha gwero) - id wotchi. Ngati seva ili ndi stratum 1, ndiye ref id ndi dzina la wotchi ya atomiki (zilembo 4 ASCII). Ngati seva ikugwiritsa ntchito seva ina, ndiye ref id ili ndi adilesi ya seva iyi.
Minda 4 yomaliza ikuyimira nthawi - 32 bits - gawo lonse, 32 bits - gawo laling'ono.
Reference - kuwerengera koloko kwaposachedwa pa seva.
Chiyambi - nthawi yomwe paketiyo idatumizidwa (yodzazidwa ndi seva - zambiri pansipa).
Landirani - nthawi yomwe paketi idalandiridwa ndi seva.
zimafalitsa - nthawi yotumiza paketi kuchokera ku seva kupita kwa kasitomala (yodzazidwa ndi kasitomala, zambiri pa izi pansipa).

Sitiganizira magawo awiri omaliza.

Tiyeni tilembe phukusi lathu:

Phukusi kodi

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

Kuti titumize (ndi kulandira) paketi ku seva, tiyenera kuyisintha kukhala gulu la byte.
Pakuchita izi (ndi kubweza), tidzalemba ntchito ziwiri - pack() ndi unpack():

paketi ntchito

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 ntchito

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

Kwa anthu aulesi, monga ntchito - kachidindo kamene kamasintha phukusi kukhala chingwe chokongola

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)

Kutumiza phukusi ku seva

Paketi yokhala ndi minda yodzaza iyenera kutumizidwa ku seva Version, mafashoni и zimafalitsa. The zimafalitsa muyenera kufotokoza nthawi panopa pa makina am'deralo (chiwerengero cha masekondi kuyambira January 1, 1900), Baibulo - aliyense wa 1-4, mode - 3 (makasitomala mumalowedwe).

Seva, itavomereza pempholi, imadzaza minda yonse mu paketi ya NTP, kukopera m'munda Chiyambi mtengo kuchokera zimafalitsa, amene anadza mu pempho. Ndi chinsinsi kwa ine chifukwa chomwe kasitomala sangathe kudzaza nthawi yomweyo mtengo wa nthawi yake m'munda Chiyambi. Zotsatira zake, paketi ikabweranso, kasitomala amakhala ndi nthawi 4 - nthawi yomwe pempholo lidatumizidwa (Chiyambi), nthawi yomwe seva idalandira pempho (Landirani), nthawi yomwe seva idatumiza yankho (zimafalitsa) ndi nthawi yomwe kasitomala adalandira yankho - Fikani (osati mu phukusi). Pogwiritsa ntchito mfundozi titha kukhazikitsa nthawi yoyenera.

Phukusi kutumiza ndi kulandira 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)

Kukonza deta kuchokera pa seva

Kukonza zidziwitso kuchokera pa seva ndikofanana ndi zomwe njonda yachingerezi kuchokera ku vuto lakale la Raymond M. Smullyan (1978): "Mwamuna m'modzi analibe wotchi yakumanja, koma kunyumba kwake kunali koloko yolondola, yomwe nthawi zina amayiwala. ku mphepo. Tsiku lina, ataiwalanso kuwongolera wotchi yake, anapita kukaona bwenzi lake, anakhala naye madzulo, ndipo atabwerera kunyumba, anakonza wotchiyo molondola. Kodi anakwanitsa bwanji kuchita zimenezi ngati nthawi yoyendayo sinadziwike pasadakhale? Yankho lake n’lakuti: “Munthu akamachoka panyumba, amapiringitsa wotchi yake n’kukumbukira malo amene manja ake ali. Atafika kwa bwenzi lake ndikusiya alendo, amalemba nthawi yakufika ndi kunyamuka. Izi zimamuthandiza kudziwa nthawi yomwe adayendera. Munthu akabwerera kunyumba n’kuyang’ana wotchi, amaona nthawi imene palibe. Mwa kuchotsa panthaŵi imeneyi nthaŵi imene anachezera, munthu amapeza nthaŵi imene amathera popita kumeneko ndi kubwerera. Mwa kuwonjezera theka la nthaŵi imene anathera panjira ku nthaŵi yochoka kwa alendo, amapeza mpata wodziŵa nthaŵi ya kufika kunyumba ndikusintha manja a wotchi yake moyenerera.”

Pezani nthawi yomwe seva ikugwira ntchito pa pempho:

  1. Pezani nthawi yoyenda ya paketi kuchokera kwa kasitomala kupita ku seva: ((Kufika - Koyambira) - (Kutumiza - Kulandila)) / 2
  2. Pezani kusiyana pakati pa kasitomala ndi nthawi ya seva:
    Landirani - Yachokera - ((Fikani - Yachokera) - (Sambani - Landirani)) / 2 =
    2 * Landirani - 2 * Oyambira - Fikani + Oyambira + Sambani - Landirani =
    Landirani - Yoyambira - Fikani + Tumizani

Timawonjezera mtengo wake ku nthawi yakomweko ndikusangalala ndi moyo.

Zotsatira zake

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)

Zothandiza ссылка.

Source: www.habr.com

Kuwonjezera ndemanga