เบเบฒเบ™เบ‚เบฝเบ™เบฅเบนเบเบ„เป‰เบฒ NTP เบ‡เปˆเบฒเบเป†

เบชเบฐเบšเบฒเบเบ”เบต, Habrusers. เบกเบทเป‰โ€‹เบ™เบตเป‰โ€‹เบ‚เป‰เบฒโ€‹เบžเบฐโ€‹เป€เบˆเบปเป‰เบฒโ€‹เบ•เป‰เบญเบ‡โ€‹เบเบฒเบ™โ€‹เบชเบปเบ™โ€‹เบ—เบฐโ€‹เบ™เบฒโ€‹เบเปˆเบฝเบงโ€‹เบเบฑเบšโ€‹เบงเบดโ€‹เบ—เบตโ€‹เบเบฒเบ™โ€‹เบ‚เบฝเบ™โ€‹เบฅเบนเบโ€‹เบ„เป‰เบฒ NTP เบ‡เปˆเบฒเบโ€‹เบ”เบฒเบโ€‹เบ‚เบญเบ‡โ€‹เบ—เปˆเบฒเบ™โ€‹เป€เบญเบ‡โ€‹. เป‚เบ”เบเบžเบทเป‰เบ™เบ–เบฒเบ™เปเบฅเป‰เบง, เบเบฒเบ™เบชเบปเบ™เบ—เบฐเบ™เบฒเบˆเบฐเบซเบฑเบ™เป„เบ›เบซเบฒเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ‚เบญเบ‡เปเบžเบฑเบเป€เบเบฑเบ”เปเบฅเบฐเบงเบดเบ—เบตเบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบเบฒเบ™เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบˆเบฒเบเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ NTP. เบฅเบฐเบซเบฑเบ”เบˆเบฐเบ–เบทเบเบ‚เบฝเบ™เปƒเบ™ Python, เป€เบžเบฒเบฐเบงเปˆเบฒเบกเบฑเบ™เป€เบšเบดเปˆเบ‡เบ„เบทเบงเปˆเบฒเบ‚เป‰เบญเบเบšเปเปˆเบกเบตเบžเบฒเบชเบฒเบ—เบตเปˆเบ”เบตเบเบงเปˆเบฒเบชเปเบฒเบฅเบฑเบšเบชเบดเปˆเบ‡เบ”เบฑเปˆเบ‡เบเปˆเบฒเบง. Connoisseurs เบˆเบฐเบชเบฑเบ‡เป€เบเบ”เป€เบซเบฑเบ™เบ„เบงเบฒเบกเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™เบ‚เบญเบ‡เบฅเบฐเบซเบฑเบ”เบ—เบตเปˆเบกเบตเบฅเบฐเบซเบฑเบ” ntplib - เบ‚เป‰เบญเบเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™ "เบ”เบปเบ™เปƒเบˆ" เบˆเบฒเบเบกเบฑเบ™.

เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™ NTP เปเบกเปˆเบ™เบซเบเบฑเบ‡? NTP เปเบกเปˆเบ™เป‚เบ›เป‚เบ•เบ„เบญเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป‚เบ•เป‰เบ•เบญเบšเบเบฑเบšเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบ—เบตเปˆเปƒเบŠเป‰เป€เบงเบฅเบฒเบ—เบตเปˆเปเบ™เปˆเบ™เบญเบ™. เป‚เบ›เป‚เบ•เบ„เบญเบ™เบ™เบตเป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเบ—เบตเปˆเบ—เบฑเบ™เบชเบฐเป„เบซเบกเบซเบผเบฒเบ. เบ•เบปเบงเบขเปˆเบฒเบ‡, เบเบฒเบ™เบšเปเบฅเบดเบเบฒเบ™ w32tm เปƒเบ™เบ›เปˆเบญเบ‡เบขเป‰เบฝเบก.

เบกเบต 5 เบฅเบธเป‰เบ™เบ‚เบญเบ‡เป‚เบ›เป‚เบ•เบ„เบญเบ™ NTP เบ—เบฑเบ‡เปเบปเบ”. เบชเบฐเบšเบฑเบšเบ—เปเบฒเบญเบดเบ”, เบฎเบธเปˆเบ™ 0 (1985, RFC958)), เบ›เบฐเบˆเบธเบšเบฑเบ™เบ–เบทเบงเปˆเบฒเบฅเป‰เบฒเบชเบฐเป„เบซเบก. เบ•เบญเบ™เบ™เบตเป‰เป€เบ„เบทเปˆเบญเบ‡เบ—เบตเปˆเปƒเปเปˆเบเบงเปˆเบฒเป„เบ”เป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰, เบ—เบต 1 (1988, RFC1059), 2nd (1989, RFC1119), 3rd (1992, RFC1305) เปเบฅเบฐ 4th (1996, RFC2030). เบฎเบธเปˆเบ™ 1-4 เปเบกเปˆเบ™เป€เบ‚เบปเป‰เบฒเบเบฑเบ™เป„เบ”เป‰เบเบฑเบšเบเบฑเบ™เปเบฅเบฐเบเบฑเบ™; เบžเบงเบเบกเบฑเบ™เปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เบžเบฝเบ‡เปเบ•เปˆเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ.

เบฎเบนเบšเปเบšเบšเบŠเบญเบ‡

เบเบฒเบ™เบ‚เบฝเบ™เบฅเบนเบเบ„เป‰เบฒ NTP เบ‡เปˆเบฒเบเป†

เบ•เบปเบงเบŠเบตเป‰เบšเบญเบเบเบฒเบ™เบเป‰เบฒเบง (เบ•เบปเบงเบŠเบตเป‰เบงเบฑเบ”เบเบฒเบ™เปเบเป‰เป„เบ‚) - เบ•เบปเบงเป€เบฅเบเบ—เบตเปˆเบŠเบตเป‰เปƒเบซเป‰เป€เบซเบฑเบ™เป€เบ–เบดเบ‡เบเบฒเบ™เป€เบ•เบทเบญเบ™เบเปˆเบฝเบงเบเบฑเบšเบเบฒเบ™เบ›เบฐเบชเบฒเบ™เบ‡เบฒเบ™เบ—เบตเบชเบญเบ‡. เบ„เบงเบฒเบกเปเบฒเบ:

  • 0 - เบšเปเปˆเบกเบตเบเบฒเบ™เปเบเป‰เป„เบ‚
  • 1 - เบ™เบฒเบ—เบตเบชเบธเบ”เบ—เป‰เบฒเบเบ‚เบญเบ‡เบกเบทเป‰เบ›เบฐเบเบญเบšเบกเบต 61 เบงเบดเบ™เบฒเบ—เบต
  • 2 โ€“ เบ™เบฒเบ—เบตเบชเบธเบ”เบ—เป‰เบฒเบเบ‚เบญเบ‡เบกเบทเป‰เบกเบต 59 เบงเบดเบ™เบฒเบ—เบต
  • 3 - เป€เบŠเบตเบšเป€เบงเบตเบฅเบปเป‰เบกเป€เบซเบฅเบง (เปเบปเบ”เป€เบงเบฅเบฒเบŠเบดเป‰เบ‡)

เบˆเปเบฒเบ™เบงเบ™เป€เบงเบตเบŠเบฑเบ™ (เบซเบกเบฒเบโ€‹เป€เบฅเบโ€‹เบชเบฐโ€‹เบšเบฑเบšโ€‹) โ€“ NTP protocol เป€เบฅเบโ€‹เป€เบงเบตโ€‹เบŠเบฑเบ™ (1-4โ€‹)โ€‹.

เบฎเบนเบšเปเบšเบšเบเบฒเบ™ (mode) โ€” เบฎเบนเบšเปเบšเบšเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ‚เบญเบ‡เบœเบนเป‰เบชเบปเปˆเบ‡เปเบžเบฑเบเป€เบเบฑเบ”. เบ„เปˆเบฒเบˆเบฒเบ 0 เบซเบฒ 7, เบ—เบปเปˆเบงเป„เบ›เบ—เบตเปˆเบชเบธเบ”:

  • 3 - เบฅเบนเบโ€‹เบ„เป‰เบฒโ€‹
  • 4 - เป€เบŠเบตเบšเป€เบงเบต
  • 5 - เบฎเบนเบšเปเบšเบšเบเบฒเบ™เบญเบญเบเบญเบฒเบเบฒเบ”

เบฅเบณ เบ•เบปเป‰เบ™ (เบฅเบฐเบ”เบฑเบšเบŠเบฑเป‰เบ™) โ€“ เบˆเบณเบ™เบงเบ™เบŠเบฑเป‰เบ™เบเบฒเบ‡เบฅเบฐเบซเบงเปˆเบฒเบ‡เป€เบŠเบตเบšเป€เบงเบต เปเบฅเบฐเป‚เบกเบ‡เบญเป‰เบฒเบ‡เบญเบตเบ‡ (1 โ€“ เป€เบŠเบตเบšเป€เบงเบตเป€เบญเบปเบฒเบ‚เปเป‰เบกเบนเบ™เป‚เบ”เบเบเบปเบ‡เบˆเบฒเบเป‚เบกเบ‡เบญเป‰เบฒเบ‡เบญเบตเบ‡, 2 โ€“ เป€เบŠเบตเบšเป€เบงเบตเป€เบญเบปเบฒเบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบเป€เบŠเบตเบšเป€เบงเบตเบ—เบตเปˆเบกเบตเบŠเบฑเป‰เบ™ 1, เปเบฅเบฐเบญเบทเปˆเบ™เป†).
เบฅเบญเบเบ™เป‰เปเบฒ เป€เบ›เบฑเบ™เบˆเบณเบ™เบงเบ™เป€เบ•เบฑเบกเบ—เบตเปˆเบฅเบปเบ‡เบฅเบฒเบเป€เบŠเบฑเบ™เป€เบ›เบฑเบ™เบ•เบปเบงเปเบ—เบ™เบ‚เบญเบ‡เบŠเปˆเบงเบ‡เป€เบงเบฅเบฒเบชเบนเบ‡เบชเบธเบ”เบฅเบฐเบซเบงเปˆเบฒเบ‡เบ‚เปเป‰เบ„เบงเบฒเบกเบ•เบดเบ”เบ•เปเปˆเบเบฑเบ™. เบฅเบนเบเบ„เป‰เบฒ NTP เบฅเบฐเบšเบธเบŠเปˆเบงเบ‡เป€เบงเบฅเบฒเบ—เบตเปˆเบกเบฑเบ™เบ„เบฒเบ”เบงเปˆเบฒเบˆเบฐเบฅเบปเบ‡เบ„เบฐเปเบ™เบ™เป€เบŠเบตเบšเป€เบงเบต, เปเบฅเบฐเป€เบŠเบตเบšเป€เบงเบต NTP เบฅเบฐเบšเบธเป„เบฅเบเบฐเบ—เบตเปˆเบกเบฑเบ™เบ„เบฒเบ”เบงเปˆเบฒเบˆเบฐเบ–เบทเบเบชเบณเบซเบผเบงเบ”. เบ„เปˆเบฒเปเบกเปˆเบ™เป€เบ—เบปเปˆเบฒเบเบฑเบšเบชเบญเบ‡ logarithm เบ‚เบญเบ‡เบงเบดเบ™เบฒเบ—เบต.
เบ„เบงเบฒเบกเปเบกเปˆเบ™เบเปเบฒ (เบ„เบงเบฒเบกเปเบกเปˆเบ™เบเปเบฒ) เป€เบ›เบฑเบ™เบˆเบณเบ™เบงเบ™เป€เบ•เบฑเบกเบ—เบตเปˆเบฅเบปเบ‡เบฅเบฒเบเป€เบŠเบฑเบ™เบชเบฐเปเบ”เบ‡เป€เบ–เบดเบ‡เบ„เบงเบฒเบกเบ–เบทเบเบ•เป‰เบญเบ‡เบ‚เบญเบ‡เป‚เบกเบ‡เบฅเบฐเบšเบปเบš. เบ„เปˆเบฒเปเบกเปˆเบ™เป€เบ—เบปเปˆเบฒเบเบฑเบšเบชเบญเบ‡ logarithm เบ‚เบญเบ‡เบงเบดเบ™เบฒเบ—เบต.
เบเบฒเบ™เบŠเบฑเบเบŠเป‰เบฒเบ‚เบญเบ‡เบฎเบฒเบ (เบ„เบงเบฒเบกเบฅเปˆเบฒเบŠเป‰เบฒเบ‚เบญเบ‡เป€เบŠเบตเบšเป€เบงเบต) โ€“ เป€เบงเบฅเบฒเบ—เบตเปˆเบกเบฑเบ™เปƒเบŠเป‰เป€เบงเบฅเบฒเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบญเปˆเบฒเบ™เป‚เบกเบ‡เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเบซเบฒเป€เบŠเบตเบšเป€เบงเบต NTP, เป€เบ›เบฑเบ™เบˆเปเบฒเบ™เบงเบ™เบˆเบธเบ”เบ„เบปเบ‡เบ—เบตเปˆเบ‚เบญเบ‡เบงเบดเบ™เบฒเบ—เบต.
เบเบฒเบ™เบเบฐเบˆเบฒเบเบ‚เบญเบ‡เบฎเบฒเบ (เบเบฒเบ™เปเบœเปˆเบเบฐเบˆเบฒเบเบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ) - เบเบฒเบ™เปเบœเปˆเบเบฐเบˆเบฒเบเบ‚เบญเบ‡เบเบฒเบ™เบญเปˆเบฒเบ™เป‚เบกเบ‡เป€เบŠเบตเบŸเป€เบงเบต NTP เป€เบ›เบฑเบ™เบˆเปเบฒเบ™เบงเบ™เบงเบดเบ™เบฒเบ—เบตเบ—เบตเปˆเบกเบตเบˆเบธเบ”เบ„เบปเบ‡เบ—เบตเปˆ.
เปเบฒเบเป€เบฅเบเบญเป‰เบฒเบ‡เบญเบตเบ‡ (ID เปเบซเบผเปˆเบ‡) โ€“ watch id. เบ–เป‰เบฒเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบกเบต stratum 1, ref id เปเบกเปˆเบ™เบŠเบทเปˆเบ‚เบญเบ‡เป‚เบกเบ‡เบ›เบฐเบฅเปเบฒเบกเบฐเบ™เบน (4 เบ•เบปเบงเบญเบฑเบเบชเบญเบ™ ASCII). เบ–เป‰เบฒเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเปƒเบŠเป‰เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบญเบทเปˆเบ™, id ref เบ›เบฐเบเบญเบšเบ”เป‰เบงเบเบ—เบตเปˆเบขเบนเปˆเบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบ™เบตเป‰.
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

เป€เบžเบทเปˆเบญเบชเบปเปˆเบ‡ (เปเบฅเบฐเบฎเบฑเบš) packet เป„เบ›เบซเบฒเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ, เบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เปƒเบซเป‰เบกเบฑเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ byte array.
เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‡เบฒเบ™เบ™เบตเป‰ (เปเบฅเบฐเบ›เบตเป‰เบ™เบเบฑเบšเบเบฑเบ™), เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ‚เบฝเบ™เบชเบญเบ‡เบซเบ™เป‰เบฒเบ—เบตเปˆ - 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))

เบŸเบฑเบ‡เบŠเบฑเบ™ unpack

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)

เบเบฒเบ™เบชเบปเปˆเบ‡เบŠเบธเบ”เป„เบ›เบซเบฒเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ

เปเบžเบฑเบเป€เบเบฑเบ”เบ—เบตเปˆเบกเบตเบŠเปˆเบญเบ‡เบ‚เปเป‰เบกเบนเบ™เป€เบ•เบฑเบกเป„เบ›เบ•เป‰เบญเบ‡เบ–เบทเบเบชเบปเปˆเบ‡เป„เบ›เบซเบฒเป€เบŠเบตเบšเป€เบงเบต Version, เบฎเบนเบšเปเบšเบšเบเบฒเบ™ ะธ เบชเบปเปˆเบ‡. เบเบฒเบ™ เบชเบปเปˆเบ‡ เบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบฅเบฐเบšเบธเป€เบงเบฅเบฒเบ›เบฐเบˆเบธเบšเบฑเบ™เบขเบนเปˆเปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เบ—เป‰เบญเบ‡เบ–เบดเปˆเบ™ (เบˆเปเบฒเบ™เบงเบ™เบงเบดเบ™เบฒเบ—เบตเบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆเบงเบฑเบ™เบ—เบต 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)

เบเบณเบฅเบฑเบ‡เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบเป€เบŠเบตเบšเป€เบงเบต

เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบเป€เบŠเบตเบšเป€เบงเบตเปเบกเปˆเบ™เบ„เป‰เบฒเบเบ„เบทเบเบฑเบšเบเบฒเบ™เบเบฐเบ—เปเบฒเบ‚เบญเบ‡เบชเบธเบžเบฒเบšเบšเบธเบฅเบธเบ”เบญเบฑเบ‡เบเบดเบ”เบˆเบฒเบเบšเบฑเบ™เบซเบฒเป€เบเบปเปˆเบฒเบ‚เบญเบ‡ Raymond M. Smullyan (1978): "เบœเบนเป‰เบŠเบฒเบเบ„เบปเบ™เบซเบ™เบถเปˆเบ‡เบšเปเปˆเบกเบตเป‚เบกเบ‡เปƒเบชเปˆเปเบ‚เบ™, เปเบ•เปˆเบกเบตเป‚เบกเบ‡เบ•เบดเบ”เบขเบนเปˆเปƒเบ™เป€เบฎเบทเบญเบ™เบ—เบตเปˆเบ–เบทเบเบ•เป‰เบญเบ‡, เป€เบŠเบดเปˆเบ‡เบšเบฒเบ‡เบ„เบฑเป‰เบ‡เบฅเบฒเบงเบฅเบทเบก. เบฅเบปเบก. เบกเบทเป‰เบซเบ™เบถเปˆเบ‡, เบฅเบทเบกเบฅเบปเบกเป‚เบกเบ‡เบ‚เบญเบ‡เบฅเบฒเบงเบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡, เบฅเบฒเบงเป„เบ›เบขเบฒเบกเบซเบกเบนเปˆเบ‚เบญเบ‡เบฅเบฒเบง, เปƒเบŠเป‰เป€เบงเบฅเบฒเบ•เบญเบ™เปเบฅเบ‡เบเบฑเบšเบฅเบฒเบง, เปเบฅเบฐเป€เบกเบทเปˆเบญเบฅเบฒเบงเบเบฑเบšเบšเป‰เบฒเบ™, เบฅเบฒเบงเบˆเบฑเบ”เบเบฒเบ™เบ•เบฑเป‰เบ‡เป‚เบกเบ‡เบขเปˆเบฒเบ‡เบ–เบทเบเบ•เป‰เบญเบ‡. เบฅเบฒเบงเบˆเบฑเบ”เบเบฒเบ™เปเบ™เบงเปƒเบ”เบ–เป‰เบฒเป€เบงเบฅเบฒเป€เบ”เบตเบ™เบ—เบฒเบ‡เบšเปเปˆเบฎเบนเป‰เบˆเบฑเบเบฅเปˆเบงเบ‡เบซเบ™เป‰เบฒ? เบ„เบณเบ•เบญเบšเบ„เบท: โ€œเป€เบกเบทเปˆเบญเบญเบญเบเบˆเบฒเบเป€เบฎเบทเบญเบ™, เบ„เบปเบ™เปœเบถเปˆเบ‡เป„เบ”เป‰เบฅเบปเบกเป‚เบกเบ‡เบ‚เบญเบ‡เบ•เบปเบ™ เปเบฅเบฐเบˆเบทเปˆเบงเปˆเบฒเบกเบทเบขเบนเปˆเปƒเบ™เบ•เบณเปเปœเปˆเบ‡เปƒเบ”. เป‚เบ”เบเป„เบ”เป‰เบกเบฒเบซเบฒเป€เบžเบทเปˆเบญเบ™เปเบฅเบฐเบญเบญเบเบˆเบฒเบเปเบ‚เบ, เบฅเบฒเบงเบชเบฑเบ‡เป€เบเบ”เป€เบซเบฑเบ™เป€เบงเบฅเบฒเบกเบฒเบฎเบญเบ”เปเบฅเบฐเบญเบญเบเป€เบ”เบตเบ™เบ—เบฒเบ‡. เบ™เบตเป‰เป€เบฎเบฑเบ”เปƒเบซเป‰เบฅเบฒเบงเบฎเบนเป‰เบงเปˆเบฒเบฅเบฒเบงเป„เบ›เบขเป‰เบฝเบกเบขเบฒเบกเบ”เบปเบ™เบ›เบฒเบ™เปƒเบ”. เบเบฑเบšเบ„เบทเบ™เบšเป‰เบฒเบ™เปเบฅเบฐเป€เบšเบดเปˆเบ‡เป‚เบกเบ‡, เบšเบธเบเบ„เบปเบ™เปƒเบ”เบซเบ™เบถเปˆเบ‡เบเปเบฒเบ™เบปเบ”เป„เบฅเบเบฐเป€เบงเบฅเบฒเบ‚เบญเบ‡เบเบฒเบ™เบšเปเปˆเบขเบนเปˆเบ‚เบญเบ‡เบฅเบฒเบง. เป‚เบ”เบเบเบฒเบ™เบซเบฑเบเบญเบญเบเบˆเบฒเบเป€เบงเบฅเบฒเบ—เบตเปˆเบฅเบฒเบงเปƒเบŠเป‰เป€เบงเบฅเบฒเป„เบ›เบขเป‰เบฝเบกเบขเบฒเบก, เบšเบธเบเบ„เบปเบ™เปƒเบ”เบซเบ™เบถเปˆเบ‡เบŠเบญเบเบซเบฒเป€เบงเบฅเบฒเบ—เบตเปˆเปƒเบŠเป‰เปƒเบ™เบเบฒเบ™เป€เบ”เบตเบ™เบ—เบฒเบ‡เบ—เบตเปˆเบ™เบฑเป‰เบ™เปเบฅเบฐเบเบฑเบšเบ„เบทเบ™. เป‚เบ”เบเบเบฒเบ™เป€เบžเบตเปˆเบกเป€เบ„เบดเปˆเบ‡เบซเบ™เบถเปˆเบ‡เบ‚เบญเบ‡เป€เบงเบฅเบฒเบ—เบตเปˆเปƒเบŠเป‰เปƒเบ™เบ–เบฐเบซเบ™เบปเบ™เป„เบ›เบชเบนเปˆเป€เบงเบฅเบฒเบญเบญเบเบˆเบฒเบเปเบ‚เบ, เบฅเบฒเบงเป„เบ”เป‰เบฎเบฑเบšเป‚เบญเบเบฒเบ”เบ—เบตเปˆเบˆเบฐเบŠเบญเบเบซเบฒเป€เบงเบฅเบฒเบกเบฒเบฎเบญเบ”เป€เบฎเบทเบญเบ™เปเบฅเบฐเบ›เบฑเบšเบกเบทเบ‚เบญเบ‡เป‚เบกเบ‡เบ‚เบญเบ‡เบฅเบฒเบงเบ•เบฒเบกเบ„เบงเบฒเบกเป€เบซเบกเบฒเบฐเบชเบปเบก.โ€

เบŠเบญเบเบซเบฒเป€เบงเบฅเบฒเบ—เบตเปˆเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเป€เบฎเบฑเบ”เบงเบฝเบเบ•เบฒเบกเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป:

  1. เบŠเบญเบเบซเบฒเป€เบงเบฅเบฒเป€เบ”เบตเบ™เบ—เบฒเบ‡เบ‚เบญเบ‡เปเบžเบฑเบเป€เบเบฑเบ”เบˆเบฒเบเบฅเบนเบเบ„เป‰เบฒเป„เบ›เบซเบฒเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ: ((เบกเบฒเบฎเบญเบ” โ€“ เบ•เบปเป‰เบ™) โ€“ (เบชเบปเปˆเบ‡ โ€“ เบฎเบฑเบš)) / 2
  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

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™