Sau NTP tus neeg siv khoom yooj yim

Nyob zoo habrausers. Hnub no kuv xav tham txog yuav ua li cas sau koj tus kheej cov neeg siv khoom yooj yim NTP. Yeej, kev sib tham yuav tig mus rau cov qauv ntawm pob ntawv thiab cov txheej txheem ntawm kev ua cov lus teb los ntawm NTP server. Cov cai yuav raug sau hauv Python, vim nws zoo li kuv tias tsis muaj lus zoo dua rau tej yam zoo li no. Connoisseurs yuav nco ntsoov qhov zoo sib xws ntawm cov cai nrog ntplib code - Kuv tau txais kev tshoov siab los ntawm nws.

Yog li NTP yog dab tsi? NTP yog tus txheej txheem rau kev sib cuam tshuam nrog lub sijhawm cov servers. Cov txheej txheem no yog siv nyob rau hauv ntau lub tshuab niaj hnub. Piv txwv li, qhov kev pabcuam w32tm ntawm windows.

Muaj 5 versions ntawm NTP raws tu qauv nyob rau hauv tag nrho. Thawj, version 0 (1985, RFC958) yog tam sim no suav tias tsis siv lawm. Cov tshiab tam sim no siv, 1st (1988, RFC1059), 2nd (1989, RFC1119), 3rd (1992, RFC1305) thiab 4th (1996, RFC2030). Versions 1-4 yog sib xws nrog ib leeg, lawv txawv tsuas yog nyob rau hauv lub algorithms ntawm cov servers.

Packet Format

Sau NTP tus neeg siv khoom yooj yim

Leap qhia (qhov taw qhia kho) - tus lej qhia ceeb toom txog kev sib koom tes thib ob. Lub ntsiab lus:

  • 0 - tsis muaj kev kho
  • 1 - feeb kawg ntawm hnub muaj 61 vib nas this
  • 2 - feeb kawg ntawm hnub muaj 59 vib nas this
  • 3 - server malfunction (lub sij hawm tsis synchronized)

Tus lej xov tooj (tus lej version) - NTP raws tu qauv tus lej (1-4).

hom (hom) β€” hom kev khiav hauj lwm ntawm cov pob ntawv xa. Tus nqi ntawm 0 txog 7, feem ntau:

  • 3 - neeg
  • 4 - server
  • 5 - hom kev tshaj tawm

stratum (txheej txheej) - tus naj npawb ntawm cov khaubncaws sab nraud povtseg ntawm cov neeg rau zaub mov thiab lub sijhawm siv sijhawm (1 - tus neeg rau zaub mov siv cov ntaub ntawv ncaj qha los ntawm lub sijhawm siv, 2 - tus neeg rau zaub mov siv cov ntaub ntawv los ntawm lub server nrog qib 1, thiab lwm yam).
pas dej ua ke yog tus lej kos npe uas sawv cev rau lub sijhawm siab tshaj plaws ntawm cov lus sib law liag. Tus neeg siv NTP qhia txog qhov ncua sij hawm ntawm qhov nws xav tias yuav xaiv cov neeg rau zaub mov, thiab NTP tus neeg rau zaub mov qhia txog lub sijhawm uas nws xav tias yuav raug xaiv. Tus nqi yog sib npaug rau binary logarithm ntawm vib nas this.
Precision (qhov tseeb) yog tus lej kos npe sawv cev rau qhov tseeb ntawm lub kaw lus moos. Tus nqi yog sib npaug rau binary logarithm ntawm vib nas this.
hauv paus ncua (neeg rau zaub mov ncua) - lub sij hawm nws yuav siv sij hawm rau lub moos nyeem kom ncav cuag NTP neeg rau zaub mov, raws li tus naj npawb ntawm cov vib nas this.
hauv paus dispersion (neeg rau zaub mov kis) - kis ntawm NTP neeg rau zaub mov moos nyeem ntawv raws li tus naj npawb ntawm cov vib nas this nrog lub ntsiab lus tas.
Ref id (qhov chaw identifier) ​​- moos id. Yog tias lub server muaj stratum 1, ces ref id yog lub npe ntawm lub moos atomic (4 ASCII cim). Yog tias tus neeg rau zaub mov siv lwm tus neeg rau zaub mov, ces tus ref id muaj qhov chaw nyob ntawm tus neeg rau zaub mov no.
Qhov kawg 4 daim teb yog lub sij hawm - 32 cov khoom - cov zauv feem, 32 khoom - cov feem.
reference - lub moos nyeem ntawv tshiab kawg ntawm lub server.
Keeb kwm - lub sij hawm thaum lub pob ntawv xa tuaj (sau los ntawm tus neeg rau zaub mov - ntxiv rau qhov no hauv qab no).
Tau txais - lub sij hawm cov pob ntawv tau txais los ntawm lub server.
Kis - Lub sijhawm xa cov pob ntawv los ntawm lub server mus rau tus neeg siv khoom (ua tiav los ntawm tus neeg siv khoom, ntxiv rau hauv qab no).

Peb yuav tsis xav txog ob qhov kawg.

Wb sau peb pob:

Pob 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

Txhawm rau xa (thiab tau txais) pob ntawv mus rau tus neeg rau zaub mov, peb yuav tsum muaj peev xwm tig nws mus rau hauv byte array.
Rau qhov no (thiab thim rov qab) kev ua haujlwm, peb yuav sau ob txoj haujlwm - pob() thiab unpack():

pob muaj nuj nqi

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 muaj nuj nqi

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

Rau cov neeg tub nkeeg, raws li daim ntawv thov - code uas hloov ib pob rau hauv ib txoj hlua zoo nkauj

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)

Xa ib pob rau lub server

Ib pob ntawv uas muaj cov teb yuav tsum raug xa mus rau lub server version, hom ΠΈ Kis. Cov Kis koj yuav tsum qhia lub sijhawm tam sim no ntawm lub tshuab hauv zos (ntau lub vib nas this txij li Lub Ib Hlis 1, 1900), version - ib qho ntawm 1-4, hom - 3 (tus neeg siv hom).

Tus neeg rau zaub mov, tau txais qhov kev thov, sau tag nrho cov teb hauv NTP pob ntawv, luam rau hauv daim teb Keeb kwm tus nqi los ntawm Kis, uas tuaj hauv kev thov. Nws yog qhov paub tsis meej rau kuv vim li cas tus neeg siv khoom tsis tuaj yeem sau tam sim ntawm tus nqi ntawm nws lub sijhawm hauv daim teb Keeb kwm. Raws li qhov tshwm sim, thaum lub pob ntawv rov qab los, tus neeg siv khoom muaj 4 lub sijhawm qhov tseem ceeb - lub sijhawm thov xa tuaj (Keeb kwm), lub sij hawm tus neeg rau zaub mov tau txais qhov kev thov (Tau txais), lub sij hawm tus neeg rau zaub mov xa cov lus teb (Kis) thiab lub sijhawm tus neeg siv khoom tau txais cov lus teb - Tuaj txog (tsis nyob hauv pob). Nrog rau cov txiaj ntsig no peb tuaj yeem teem sijhawm kom raug.

Pob xa thiab txais 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)

Kev ua cov ntaub ntawv los ntawm lub server

Kev ua cov ntaub ntawv los ntawm cov neeg rau zaub mov zoo ib yam li kev ua ntawm tus txiv neej Askiv los ntawm qhov teeb meem qub ntawm Raymond M. Smullyan (1978): "Ib tug txiv neej tsis muaj lub dab teg, tab sis muaj lub moos moos hauv tsev, uas qee zaum nws tsis nco qab. rau cua. Muaj ib hnub, nws tsis nco qab cua nws lub moos dua, nws mus ntsib nws tus phooj ywg, siv sijhawm yav tsaus ntuj nrog nws, thiab thaum nws rov los tsev, nws tswj hwm lub moos kom raug. Nws tau tswj xyuas qhov no li cas yog tias lub sijhawm taug kev tsis tau paub ua ntej? Lo lus teb yog: β€œThaum tawm hauv tsev, ib tug neeg cua nws lub moos thiab nco ntsoov tias ob txhais tes nyob rau hauv txoj hauj lwm. Tau tuaj rau ib tug phooj ywg thiab tawm hauv cov qhua, nws sau lub sijhawm nws tuaj txog thiab tawm mus. Qhov no ua rau nws paub tias nws mus xyuas ntev npaum li cas. Rov qab mus tsev thiab saib lub moos, tus neeg txiav txim siab txog lub sijhawm nws tsis tuaj. Los ntawm rho tawm lub sijhawm no lub sijhawm nws mus xyuas, tus neeg pom lub sijhawm siv mus ncig thiab rov qab los. Los ntawm kev ntxiv ib nrab ntawm lub sijhawm siv ntawm txoj kev mus rau lub sijhawm tawm ntawm cov qhua, nws tau txais lub sijhawm los nrhiav lub sijhawm los txog hauv tsev thiab kho ob txhais tes ntawm nws lub moos raws li. "

Nrhiav lub sijhawm tus neeg rau zaub mov ua haujlwm ntawm qhov kev thov:

  1. Nrhiav lub sijhawm mus ncig ntawm pob ntawv los ntawm tus neeg siv khoom mus rau lub server: ((Sau – Keeb Kwm) – (Xa – Txais)) / 2
  2. Nrhiav qhov txawv ntawm tus neeg siv khoom thiab lub sijhawm server:
    Txais - Keeb Kwm - (( Tuaj txog - Keeb Kwm ) - (Hloov - Txais)) / 2 =
    2 * Tau txais – 2 * Keeb Kwm – Mus Txog + Keeb Kwm + Xaus – Tau txais =
    Txais - Originate - Tuaj + Xa

Peb ntxiv cov txiaj ntsig tshwm sim rau lub sijhawm hauv zos thiab txaus siab rau lub neej.

Cov zis tawm

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)

Pab tau txuas.

Tau qhov twg los: www.hab.com

Ntxiv ib saib