рдПрдХ рд╕рд╛рдзрд╛ NTP рдХреНрд▓рд╛рдпрдВрдЯ рд▓рд┐рд╣рд┐рдд рдЖрд╣реЗ

рдирдорд╕реНрдХрд╛рд░, рд╣реЕрдмреНрд░реЛрдЭрд░реНрд╕. рдЖрдЬ рдорд▓рд╛ рддреБрдордЪрд╛ рд╕реНрд╡рддрдГрдЪрд╛ рд╕рд╛рдзрд╛ NTP рдХреНрд▓рд╛рдпрдВрдЯ рдХрд╕рд╛ рд▓рд┐рд╣рд╛рдпрдЪрд╛ рдпрд╛рдмрджреНрджрд▓ рдмреЛрд▓рд╛рдпрдЪреЗ рдЖрд╣реЗ. рдореБрд│рд╛рдд, рд╕рдВрднрд╛рд╖рдг рдкреЕрдХреЗрдЯрдЪреНрдпрд╛ рд╕рдВрд░рдЪрдиреЗрдХрдбреЗ рдЖрдгрд┐ NTP рд╕рд░реНрд╡реНрд╣рд░рдХрдбреВрди рдкреНрд░рддрд┐рд╕рд╛рджрд╛рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рдкрджреНрдзрддреАрдХрдбреЗ рд╡рд│реЗрд▓. рдХреЛрдб рдкрд╛рдпрдердирдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓рд╛ рдЬрд╛рдИрд▓, рдХрд╛рд░рдг рдорд▓рд╛ рдЕрд╕реЗ рд╡рд╛рдЯрддреЗ рдХреА рдЕрд╢рд╛ рдЧреЛрд╖реНрдЯреАрдВрд╕рд╛рдареА рдХреЛрдгрддреАрд╣реА рдЪрд╛рдВрдЧрд▓реА рднрд╛рд╖рд╛ рдирд╛рд╣реА. рдкрд╛рд░рдЦреА ntplib рдХреЛрдбрд╕рд╣ рдХреЛрдбрдЪреА рд╕рдорд╛рдирддрд╛ рд▓рдХреНрд╖рд╛рдд рдШреЗрддреАрд▓ - рдорд▓рд╛ рддреНрдпрд╛рддреВрди "рдкреНрд░реЗрд░рдгрд╛" рдорд┐рд│рд╛рд▓реА.

рдордЧ NTP рдореНрд╣рдгрдЬреЗ рдирдХреНрдХреА рдХрд╛рдп? NTP рд╣рд╛ рдЕрдЪреВрдХ рд╡реЗрд│ рд╕рд░реНрд╡реНрд╣рд░рд╕рд╣ рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рджрд╛рд╕рд╛рдареА рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдЖрд╣реЗ. рд╣рд╛ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдЕрдиреЗрдХ рдЖрдзреБрдирд┐рдХ рдорд╢реАрдирдордзреНрдпреЗ рд╡рд╛рдкрд░рд▓рд╛ рдЬрд╛рддреЛ. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рд╡рд┐рдВрдбреЛрдЬрдордзреАрд▓ w32tm рд╕реЗрд╡рд╛.

NTP рдкреНрд░реЛрдЯреЛрдХреЙрд▓рдЪреНрдпрд╛ рдПрдХреВрдг 5 рдЖрд╡реГрддреНрддреНрдпрд╛ рдЖрд╣реЗрдд. рдкрд╣рд┐рд▓реА, рдЖрд╡реГрддреНрддреА 0 (1985, RFC958)), рд╕рдзреНрдпрд╛ рдЕрдкреНрд░рдЪрд▓рд┐рдд рдорд╛рдирд▓реА рдЬрд╛рддреЗ. рдЖрддрд╛ рдирд╡реАрди рд╡рд╛рдкрд░рд▓реЗ рдЬрд╛рддрд╛рдд, 1 рд▓рд╛ (1988, RFC1059), 2рд░рд╛ (1989, RFC1119), рддрд┐рд╕рд░рд╛ (3, RFC1992) рдЖрдгрд┐ 1305 рдерд╛ (4, RFC1996). рдЖрд╡реГрддреНрддреНрдпрд╛ 2030-1 рдПрдХрдореЗрдХрд╛рдВрд╢реА рд╕реБрд╕рдВрдЧрдд рдЖрд╣реЗрдд; рддреНрдпрд╛ рдлрдХреНрдд рд╕рд░реНрд╡реНрд╣рд░ рдСрдкрд░реЗрд╢рди рдЕрд▓реНрдЧреЛрд░рд┐рджрдордордзреНрдпреЗ рднрд┐рдиреНрди рдЖрд╣реЗрдд.

рдкреЕрдХреЗрдЬрдЪреЗ рд╕реНрд╡рд░реВрдк

рдПрдХ рд╕рд╛рдзрд╛ NTP рдХреНрд▓рд╛рдпрдВрдЯ рд▓рд┐рд╣рд┐рдд рдЖрд╣реЗ

рд▓реАрдк рдЗрдВрдбрд┐рдХреЗрдЯрд░ (рд╕реБрдзрд╛рд░рдгрд╛ рд╕реВрдЪрдХ) - рд╕рдордиреНрд╡рдп рд╕реЗрдХрдВрджрд╛рдмрджреНрджрд▓ рдЪреЗрддрд╛рд╡рдгреА рджрд░реНрд╢рд╡рдгрд╛рд░реА рд╕рдВрдЦреНрдпрд╛. рдЕрд░реНрде:

  • 0 - рд╕реБрдзрд╛рд░рдгрд╛ рдирд╛рд╣реА
  • 1 - рджрд┐рд╡рд╕рд╛рдЪреНрдпрд╛ рд╢реЗрд╡рдЯрдЪреНрдпрд╛ рдорд┐рдирд┐рдЯрд╛рдд 61 рд╕реЗрдХрдВрдж рдЕрд╕рддрд╛рдд
  • 2 - рджрд┐рд╡рд╕рд╛рдЪреНрдпрд╛ рд╢реЗрд╡рдЯрдЪреНрдпрд╛ рдорд┐рдирд┐рдЯрд╛рдд 59 рд╕реЗрдХрдВрдж рдЕрд╕рддрд╛рдд
  • 3 - рд╕рд░реНрд╡реНрд╣рд░ рдЦрд░рд╛рдмреА (рд╡реЗрд│ рд╕рдордХреНрд░рдорд┐рдд рдирд╛рд╣реА)

рдЖрд╡реГрддреНрддреА рдХреНрд░рдорд╛рдВрдХ (рдЖрд╡реГрддреНрддреА рдХреНрд░рдорд╛рдВрдХ) тАУ NTP рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдЖрд╡реГрддреНрддреА рдХреНрд░рдорд╛рдВрдХ (1-4).

рдореЛрдб (рдореЛрдб) - рдкреЕрдХреЗрдЯ рдкреНрд░реЗрд╖рдХрд╛рдЪрд╛ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рдореЛрдб. 0 рддреЗ 7 рдкрд░реНрдпрдВрддрдЪреЗ рдореВрд▓реНрдп, рд╕рд░реНрд╡рд╛рдд рд╕рд╛рдорд╛рдиреНрдп:

  • 3 - рдЧреНрд░рд╛рд╣рдХ
  • 4 - рд╕рд░реНрд╡реНрд╣рд░
  • 5 - рдкреНрд░рд╕рд╛рд░рдг рдореЛрдб

рд╕реНрдЯреНрд░реЕрдЯрдо (рд▓реЗрдпрд░рд┐рдВрдЧ рд▓реЗрд╡реНрд╣рд▓) тАУ рд╕рд░реНрд╡реНрд╣рд░ рдЖрдгрд┐ рд╕рдВрджрд░реНрдн рдШрдбреНрдпрд╛рд│ рджрд░рдореНрдпрд╛рдирдЪреНрдпрд╛ рдордзреНрдпрд╡рд░реНрддреА рд╕реНрддрд░рд╛рдВрдЪреА рд╕рдВрдЦреНрдпрд╛ (1 тАУ рд╕рд░реНрд╡реНрд╣рд░ рдереЗрдЯ рд╕рдВрджрд░реНрдн рдШрдбреНрдпрд╛рд│рд╛рддреВрди рдбреЗрдЯрд╛ рдШреЗрддреЛ, 2 тАУ рд╕рд░реНрд╡реНрд╣рд░ рд▓реЗрдпрд░ 1 рдЗ.рд╕рд╣ рд╕рд░реНрд╡реНрд╣рд░рд╡рд░реВрди рдбреЗрдЯрд╛ рдШреЗрддреЛ).
рдкреВрд▓ рд╕рд▓рдЧ рд╕рдВрджреЗрд╢рд╛рдВрдордзреАрд▓ рдХрдорд╛рд▓ рдЕрдВрддрд░рд╛рдЪреЗ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдгрд╛рд░рд╛ рдПрдХ рд╕реНрд╡рд╛рдХреНрд╖рд░реА рдкреВрд░реНрдгрд╛рдВрдХ рдЖрд╣реЗ. NTP рдХреНрд▓рд╛рдпрдВрдЯ рдЬреНрдпрд╛ рдЕрдВрддрд░рд╛рдиреЗ рд╕рд░реНрд╡реНрд╣рд░рд▓рд╛ рдорддрджрд╛рди рдХрд░рдгреНтАНрдпрд╛рдЪреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреЛ рддреЛ рдЕрдВрддрд░рд╛рд▓ рдпреЗрдереЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЛ рдЖрдгрд┐ NTP рд╕рд░реНрд╡реНрд╣рд░ рдЬреНрдпрд╛ рдЕрдВрддрд░рд╛рд╡рд░ рдорддрджрд╛рди рдХрд░рдгреНтАНрдпрд╛рдЪреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреЛ рддреЛ рдЕрдВрддрд░рд╛рд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЛ. рдореВрд▓реНрдп рд╕реЗрдХрдВрджрд╛рдВрдЪреНрдпрд╛ рдмрд╛рдпрдирд░реА рд▓реЙрдЧрд░рд┐рдердордЪреНрдпрд╛ рдмрд░реЛрдмрд░реАрдЪреЗ рдЖрд╣реЗ.
рдкреНрд░рд┐рд╕рд┐рдЬрди (рдЕрдЪреВрдХрддрд╛) рд╣реА рд╕рд┐рд╕реНрдЯреАрдо рдШрдбреНрдпрд╛рд│рд╛рдЪреА рдЕрдЪреВрдХрддрд╛ рджрд░реНрд╢рд╡рд┐рдгрд╛рд░реА рдПрдХ рд╕реНрд╡рд╛рдХреНрд╖рд░реА рдкреВрд░реНрдгрд╛рдВрдХ рдЖрд╣реЗ. рдореВрд▓реНрдп рд╕реЗрдХрдВрджрд╛рдВрдЪреНрдпрд╛ рдмрд╛рдпрдирд░реА рд▓реЙрдЧрд░рд┐рдердордЪреНрдпрд╛ рдмрд░реЛрдмрд░реАрдЪреЗ рдЖрд╣реЗ.
рд░реВрдЯ рд╡рд┐рд▓рдВрдм (рд╕рд░реНрд╡реНрд╣рд░ рд╡рд┐рд▓рдВрдм) тАУ рдШрдбреНрдпрд╛рд│рд╛рдЪреНрдпрд╛ рд╡рд╛рдЪрдирд╛рдВрдирд╛ NTP рд╕рд░реНрд╡реНрд╣рд░рдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪрдгреНрдпрд╛рд╕рд╛рдареА рд▓рд╛рдЧрдгрд╛рд░рд╛ рд╡реЗрд│, рд╕реЗрдХрдВрджрд╛рдВрдЪреНрдпрд╛ рдирд┐рд╢реНрдЪрд┐рдд-рдмрд┐рдВрджреВ рд╕рдВрдЦреНрдпреЗрдкреНрд░рдорд╛рдгреЗ.
рд░реВрдЯ рдлреИрд▓рд╛рд╡ (рд╕рд░реНрд╡реНрд╣рд░ рд╕реНрдкреНрд░реЗрдб) - рдПрдирдЯреАрдкреА рд╕рд░реНрд╡реНрд╣рд░ рдХреНрд▓реЙрдХ рд░реАрдбрд┐рдВрдЧрдЪрд╛ рдкреНрд░рд╕рд╛рд░ рдПрдХрд╛ рдирд┐рд╢реНрдЪрд┐рдд рдмрд┐рдВрджреВрд╕рд╣ рд╕реЗрдХрдВрджрд╛рдВрдЪреНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдкреНрд░рдорд╛рдгреЗ.
рд╕рдВрджрд░реНрдн рдЖрдпрдбреА (рд╕реНрд░реЛрдд рдЕрднрд┐рдЬреНрдЮрд╛рдкрдХ) - рдШрдбреНрдпрд╛рд│ рдЖрдпрдбреА. рдЬрд░ рд╕рд░реНрд╡реНрд╣рд░рдордзреНрдпреЗ рд╕реНрдЯреНрд░реЕрдЯрдо 1 рдЕрд╕реЗрд▓, рддрд░ рд░реЗрдл рдЖрдпрдбреА рд╣реЗ рдЕрдгреБ рдШрдбреНрдпрд╛рд│рд╛рдЪреЗ рдирд╛рд╡ рдЖрд╣реЗ (4 ASCII рд╡рд░реНрдг). рдЬрд░ рд╕рд░реНрд╡реНрд╣рд░ рджреБрд╕рд░рд╛ рд╕рд░реНрд╡реНрд╣рд░ рд╡рд╛рдкрд░рдд рдЕрд╕реЗрд▓, рддрд░ рд░реЗрдл рдЖрдпрдбреАрдордзреНрдпреЗ рдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рдЪрд╛ рдкрддреНрддрд╛ рдЕрд╕рддреЛ.
рд╢реЗрд╡рдЯрдЪреА 4 рдлреАрд▓реНрдб рд╡реЗрд│ рджрд░реНрд╢рд╡рддрд╛рдд - 32 рдмрд┐рдЯреНрд╕ - рдкреВрд░реНрдгрд╛рдВрдХ рднрд╛рдЧ, 32 рдмрд┐рдЯреНрд╕ - рдлреНрд░реЕрдХреНрд╢рдирд▓ рднрд╛рдЧ.
рд╕рдВрджрд░реНрдн - рд╕рд░реНрд╡реНрд╣рд░рд╡рд░реАрд▓ рдирд╡реАрдирддрдо рдШрдбреНрдпрд╛рд│ рд╡рд╛рдЪрди.
рдореВрд│ - рдЬреЗрд╡реНрд╣рд╛ рдкреЕрдХреЗрдЯ рдкрд╛рдард╡рд▓реЗ рдЧреЗрд▓реЗ рддреЗрд╡реНрд╣рд╛рдЪреА рд╡реЗрд│ (рд╕рд░реНрд╡реНрд╣рд░рджреНрд╡рд╛рд░реЗ рднрд░рд▓реЗрд▓реА - рдЦрд╛рд▓реА рдпрд╛рдмрджреНрджрд▓ рдЕрдзрд┐рдХ).
рдкреНрд░рд╛рдкреНрдд - рд╕рд░реНрд╡реНрд╣рд░рджреНрд╡рд╛рд░реЗ рдкреЕрдХреЗрдЯ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдгреНрдпрд╛рдЪреА рд╡реЗрд│.
рдкреНрд░рдХреНрд╖реЗрдкрд┐рдд - рд╕рд░реНрд╡реНрд╣рд░рд╡рд░реВрди рдХреНрд▓рд╛рдпрдВрдЯрд▓рд╛ рдкреЕрдХреЗрдЯ рдкрд╛рдард╡рдгреНрдпрд╛рдЪреА рд╡реЗрд│ (рдХреНрд▓рд╛рдпрдВрдЯрдиреЗ рднрд░рд▓реЗрд▓реА, рдЦрд╛рд▓реА рдпрд╛рдмрджреНрджрд▓ рдЕрдзрд┐рдХ).

рдЖрдореНрд╣реА рд╢реЗрд╡рдЯрдЪреНрдпрд╛ рджреЛрди рдлреАрд▓реНрдбрдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХрд░рдгрд╛рд░ рдирд╛рд╣реА.

рдЪрд▓рд╛ рдЖрдордЪреЗ рдкреЕрдХреЗрдЬ рд▓рд┐рд╣реВ:

рдкреЕрдХреЗрдЬ рдХреЛрдб

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

рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдкреЕрдХреЗрдЯ рдкрд╛рдард╡рдгреНрдпрд╛рд╕рд╛рдареА (рдЖрдгрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА), рдЖрдореНрд╣реА рддреЗ рдмрд╛рдЗрдЯ рдЕреЕрд░реЗрдордзреНрдпреЗ рдмрджрд▓рдгреНрдпрд╛рд╕ рд╕рдХреНрд╖рдо рдЕрд╕рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.
рдпрд╛ (рдЖрдгрд┐ рдЙрд▓рдЯ) рдСрдкрд░реЗрд╢рдирд╕рд╛рдареА, рдЖрдореНрд╣реА рджреЛрди рдлрдВрдХреНрд╢рдиреНрд╕ рд▓рд┐рд╣реВ - pack() рдЖрдгрд┐ unpack():

рдкреЕрдХ рдлрдВрдХреНрд╢рди

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

рдЕрдирдкреЕрдХ рдлрдВрдХреНрд╢рди

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

рдЖрд│рд╢реА рд▓реЛрдХрд╛рдВрд╕рд╛рдареА, рдПрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдореНрд╣рдгреВрди - рдХреЛрдб рдЬреЛ рдкреЕрдХреЗрдЬрд▓рд╛ рд╕реБрдВрджрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧрдордзреНрдпреЗ рдмрджрд▓рддреЛ

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)

рд╕рд░реНрд╡реНрд╣рд░рд╡рд░ рдкреЕрдХреЗрдЬ рдкрд╛рдард╡рдд рдЖрд╣реЗ

рднрд░рд▓реЗрд▓реНрдпрд╛ рдлреАрд▓реНрдбрд╕рд╣ рдПрдХ рдкреЕрдХреЗрдЯ рд╕рд░реНрд╡реНрд╣рд░рд▓рд╛ рдкрд╛рдард╡рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ рдЖрд╡реГрддреНрддреА, рдореЛрдб ╨╕ рдкреНрд░рдХреНрд╖реЗрдкрд┐рдд. рдж рдкреНрд░рдХреНрд╖реЗрдкрд┐рдд рддреБрдореНрд╣реА рд╕реНрдерд╛рдирд┐рдХ рдорд╢реАрдирд╡рд░ рд╡рд░реНрддрдорд╛рди рд╡реЗрд│ (1 рдЬрд╛рдиреЗрд╡рд╛рд░реА 1900 рдкрд╛рд╕реВрди рд╕реЗрдХрдВрджрд╛рдВрдЪреА рд╕рдВрдЦреНрдпрд╛), рдЖрд╡реГрддреНрддреА - 1-4 рдкреИрдХреА рдХреЛрдгрддреАрд╣реА, рдореЛрдб - 3 (рдХреНрд▓рд╛рдпрдВрдЯ рдореЛрдб) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

рд╕рд░реНрд╡реНрд╣рд░, рд╡рд┐рдирдВрддреА рд╕реНрд╡реАрдХрд╛рд░рд▓реНрдпрд╛рдирдВрддрд░, NTP рдкреЕрдХреЗрдЯрдордзреАрд▓ рд╕рд░реНрд╡ рдлреАрд▓реНрдб рднрд░рддреЛ, рдлреАрд▓реНрдбрдордзреНрдпреЗ рдХреЙрдкреА рдХрд░рддреЛ рдореВрд│ рдкрд╛рд╕реВрди рдореВрд▓реНрдп рдкреНрд░рдХреНрд╖реЗрдкрд┐рдд, рдЬреЗ рд╡рд┐рдирдВрддреАрдордзреНрдпреЗ рдЖрд▓реЗ. рд╣реЗ рдорд╛рдЭреНрдпрд╛рд╕рд╛рдареА рдПрдХ рдЧреВрдв рдЖрд╣реЗ рдХреА рдХреНрд▓рд╛рдпрдВрдЯ рддреНрдпрд╛рдЪреНрдпрд╛ рдлреАрд▓реНрдбрдордзреАрд▓ рд╡реЗрд│реЗрдЪреЗ рдореВрд▓реНрдп рддреНрд╡рд░рд┐рдд рдХрд╛ рднрд░реВ рд╢рдХрдд рдирд╛рд╣реА рдореВрд│. рдкрд░рд┐рдгрд╛рдореА, рдЬреЗрд╡реНрд╣рд╛ рдкреЕрдХреЗрдЯ рдкрд░рдд рдпреЗрддреЗ, рддреЗрд╡реНрд╣рд╛ рдХреНрд▓рд╛рдпрдВрдЯрдХрдбреЗ 4 рд╡реЗрд│реЗрдЪреА рдореВрд▓реНрдпреЗ рдЕрд╕рддрд╛рдд - рд╡рд┐рдирдВрддреА рдкрд╛рдард╡рд┐рдгреНрдпрд╛рдЪреА рд╡реЗрд│ (рдореВрд│), рд╕рд░реНрд╡реНрд╣рд░рд▓рд╛ рд╡рд┐рдирдВрддреА рдкреНрд░рд╛рдкреНрдд рд╣реЛрдгреНрдпрд╛рдЪреА рд╡реЗрд│ (рдкреНрд░рд╛рдкреНрдд), рд╕рд░реНрд╡реНрд╣рд░рдиреЗ рдкреНрд░рддрд┐рд╕рд╛рдж рдкрд╛рдард╡рдгреНрдпрд╛рдЪреА рд╡реЗрд│ (рдкреНрд░рдХреНрд╖реЗрдкрд┐рдд) рдЖрдгрд┐ рдХреНрд▓рд╛рдпрдВрдЯрд▓рд╛ рдкреНрд░рддрд┐рд╕рд╛рдж рдорд┐рд│рд╛рд▓реНрдпрд╛рдЪреА рд╡реЗрд│ - рдЖрдЧрдорди (рдкреЕрдХреЗрдЬрдордзреНрдпреЗ рдирд╛рд╣реА). рдпрд╛ рдореВрд▓реНрдпрд╛рдВрдЪрд╛ рд╡рд╛рдкрд░ рдХрд░реВрди рдЖрдкрдг рдпреЛрдЧреНрдп рд╡реЗрд│ рд╕реЗрдЯ рдХрд░реВ рд╢рдХрддреЛ.

рдкреЕрдХреЗрдЬ рдкрд╛рдард╡рдгреЗ рдЖрдгрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгреЗ рдХреЛрдб

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

рд╕рд░реНрд╡реНрд╣рд░рд╡рд░реВрди рдбреЗрдЯрд╛рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдд рдЖрд╣реЗ

рд╕рд░реНрд╡реНрд╣рд░рд╡рд░реАрд▓ рдбреЗрдЯрд╛рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреЗ рд╣реЗ рд░реЗрдордВрдб рдПрдо. рд╕реНрдореБрд▓реНрдпрди (1978) рдЪреНрдпрд╛ рдЬреБрдиреНрдпрд╛ рд╕рдорд╕реНрдпреЗрддреАрд▓ рдЗрдВрдЧреНрд░рдЬреА рдЧреГрд╣рд╕реНрдерд╛рдВрдЪреНрдпрд╛ рдХреГрддреАрдВрд╕рд╛рд░рдЦреЗрдЪ рдЖрд╣реЗ: тАЬрдПрдХрд╛ рдорд╛рдгрд╕рд╛рдХрдбреЗ рдордирдЧрдЯрд╛рдЪреЗ рдШрдбреНрдпрд╛рд│ рдирд╡реНрд╣рддреЗ, рдкрд░рдВрддреБ рдШрд░реА рдПрдХ рдЕрдЪреВрдХ рднрд┐рдВрдд рдШрдбреНрдпрд╛рд│ рд╣реЛрддреЗ, рдЬреЗ рддреЛ рдХрдзреАрдХрдзреА рд╡рд┐рд╕рд░рд▓рд╛. рд╡рд╛рд░рд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдПрдХреЗ рджрд┐рд╡рд╢реА, рдкреБрдиреНрд╣рд╛ рдШрдбреНрдпрд╛рд│ рд╡рд│рд╡рд╛рдпрд▓рд╛ рд╡рд┐рд╕рд░рд▓реНрдпрд╛рдиреЗ, рддреЛ рдЖрдкрд▓реНрдпрд╛ рдорд┐рддреНрд░рд╛рд▓рд╛ рднреЗрдЯрд╛рдпрд▓рд╛ рдЧреЗрд▓рд╛, рддреНрдпрд╛рдЪреНрдпрд╛рдмрд░реЛрдмрд░ рд╕рдВрдзреНрдпрд╛рдХрд╛рд│ рдШрд╛рд▓рд╡рд▓реА рдЖрдгрд┐ рдШрд░реА рдкрд░рддрд▓реНрдпрд╛рд╡рд░ рддреНрдпрд╛рдиреЗ рдШрдбреНрдпрд╛рд│ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рд╕реЗрдЯ рдХреЗрд▓реЗ. рдкреНрд░рд╡рд╛рд╕рд╛рдЪреА рд╡реЗрд│ рдЕрдЧреЛрджрд░рдЪ рдорд╛рд╣реАрдд рдирд╕реЗрд▓ рддрд░ рддреНрдпрд╛рдиреЗ рд╣реЗ рдХрд╕реЗ рдХреЗрд▓реЗ? рдЙрддреНрддрд░ рдЖрд╣реЗ: тАЬрдШрд░ рд╕реЛрдбрддрд╛рдирд╛, рдПрдЦрд╛рджреА рд╡реНрдпрдХреНрддреА рдЖрдкрд▓реЗ рдШрдбреНрдпрд╛рд│ рд╡рд╛рд░рд╛ рдХрд░рддреЗ рдЖрдгрд┐ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рддреЗ рдХреА рд╣рд╛рдд рдХреЛрдгрддреНрдпрд╛ рд╕реНрдерд┐рддреАрдд рдЖрд╣реЗрдд. рдорд┐рддреНрд░рд╛рдХрдбреЗ рдЖрд▓реНрдпрд╛рд╡рд░ рдЖрдгрд┐ рдкрд╛рд╣реБрдгреНрдпрд╛рдВрдирд╛ рд╕реЛрдбрд▓реНрдпрд╛рдирдВрддрд░, рддреЛ рддреНрдпрд╛рдЪреНрдпрд╛ рдпреЗрдгреНрдпрд╛рдЪреА рдЖрдгрд┐ рдЬрд╛рдгреНрдпрд╛рдЪреА рд╡реЗрд│ рдиреЛрдВрджрд╡рддреЛ. рд╣реЗ рддреНрдпрд╛рд▓рд╛ рдХрд┐рддреА рдХрд╛рд│ рднреЗрдЯ рджреЗрдд рд╣реЛрддреЗ рд╣реЗ рд╢реЛрдзреВ рджреЗрддреЗ. рдШрд░реА рдкрд░рдд рдпреЗрддрд╛рдирд╛ рдЖрдгрд┐ рдШрдбреНрдпрд╛рд│рд╛рдХрдбреЗ рдкрд╛рд╣рддрд╛рдирд╛, рдПрдЦрд╛рджреА рд╡реНрдпрдХреНрддреА рддреНрдпрд╛рдЪреНрдпрд╛ рдЕрдиреБрдкрд╕реНрдерд┐рддреАрдЪрд╛ рдХрд╛рд▓рд╛рд╡рдзреА рдард░рд╡рддреЗ. рдпрд╛ рд╡реЗрд│реЗрддреВрди рддреНрдпрд╛рдиреЗ рднреЗрдЯреАрд╕рд╛рдареА рдШрд╛рд▓рд╡рд▓реЗрд▓рд╛ рд╡реЗрд│ рд╡рдЬрд╛ рдХреЗрд▓реНрдпрд╛рд╕, рдПрдЦрд╛рджреНрдпрд╛ рд╡реНрдпрдХреНрддреАрдиреЗ рддреЗрдереЗ рдЖрдгрд┐ рдорд╛рдЧреЗ рдкреНрд░рд╡рд╛рд╕ рдХрд░рдгреНрдпрд╛рдд рдШрд╛рд▓рд╡рд▓реЗрд▓рд╛ рд╡реЗрд│ рд╢реЛрдзрд▓рд╛ рдЬрд╛рддреЛ. рдкрд╛рд╣реБрдгреНрдпрд╛рдВрдирд╛ рд╕реЛрдбрдгреНрдпрд╛рдЪреНрдпрд╛ рд╡реЗрд│реЗрдд рд░рд╕реНрддреНрдпрд╛рд╡рд░ рдШрд╛рд▓рд╡рд▓реЗрд▓рд╛ рдЕрд░реНрдзрд╛ рд╡реЗрд│ рдЬреЛрдбреВрди, тАЛтАЛрддреНрдпрд╛рд▓рд╛ рдШрд░реА рдпреЗрдгреНрдпрд╛рдЪреА рд╡реЗрд│ рд╢реЛрдзрдгреНрдпрд╛рдЪреА рдЖрдгрд┐ рддреНрдпрд╛рдиреБрд╕рд╛рд░ рдШрдбреНрдпрд╛рд│рд╛рдЪреЗ рд╣рд╛рдд рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рд╕рдВрдзреА рдорд┐рд│рддреЗ.тАЭ

рд╡рд┐рдирдВрддреАрд╡рд░ рд╕рд░реНрд╡реНрд╣рд░ рдХрд┐рддреА рд╡реЗрд│ рдХрд╛рдо рдХрд░рдд рдЖрд╣реЗ рддреЗ рд╢реЛрдзрд╛:

  1. рдХреНрд▓рд╛рдпрдВрдЯрдкрд╛рд╕реВрди рд╕рд░реНрд╡реНрд╣рд░рдкрд░реНрдпрдВрдд рдкреЕрдХреЗрдЯрдЪрд╛ рдкреНрд░рд╡рд╛рд╕ рд╡реЗрд│ рд╢реЛрдзрд╛: ((рдЖрдЧрдорди тАУ рдЙрддреНрдкрддреНрддреА) тАУ (рдкреНрд░рд╕рд╛рд░рдг тАУ рдкреНрд░рд╛рдкреНрдд)) / реи
  2. рдХреНрд▓рд╛рдпрдВрдЯ рдЖрдгрд┐ рд╕рд░реНрд╡реНрд╣рд░рдЪреНрдпрд╛ рд╡реЗрд│реЗрддреАрд▓ рдлрд░рдХ рд╢реЛрдзрд╛:
    рдкреНрд░рд╛рдкреНрдд рдХрд░рд╛ - рдореВрд│ - ((рдЖрдЧрдорди - рдЙрддреНрдкрддреНрддреА) - (рдкреНрд░рд╕рд╛рд░рдг - рдкреНрд░рд╛рдкреНрдд рдХрд░рд╛)) / 2 =
    2 * рдкреНрд░рд╛рдкреНрдд рдХрд░рд╛ - 2 * рдЙрддреНрдкрддреНрддрд┐ - рдЖрдЧрдорди + рдЙрддреНрдкрддреНрддрд┐ + рдкреНрд░рд╕рд╛рд░рд┐рдд - рдкреНрд░рд╛рдкреНрдд =
    рдкреНрд░рд╛рдкреНрдд рдХрд░рд╛ - рдореВрд│ - рдЖрдЧрдорди + рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рд╛

рдЖрдореНрд╣реА рд╕реНрдерд╛рдирд┐рдХ рд╡реЗрд│реЗрдд рдкрд░рд┐рдгрд╛рдореА рдореВрд▓реНрдп рдЬреЛрдбрддреЛ рдЖрдгрд┐ рдЬреАрд╡рдирд╛рдЪрд╛ рдЖрдирдВрдж рдШреЗрддреЛ.

рдирд┐рдХрд╛рд▓рд╛рдЪреЗ рдЖрдЙрдЯрдкреБрдЯ

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)

рдЙрдкрдпреБрдХреНрдд ╤Б╤Б╤Л╨╗╨║╨░.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛