αžŸαžšαžŸαŸαžšαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž—αŸ’αž‰αŸ€αžœ NTP αžŸαžΆαž˜αž‰αŸ’αž‰

αžŸαž½αžŸαŸ’αžŠαžΈβ€‹αž’αŸ’αž“αž€β€‹αž”αŸ’αžšαžΎβ€‹αž”αŸ’αžšαžΆαžŸαŸ‹αŸ” αžαŸ’αž„αŸƒαž“αŸαŸ‡αžαŸ’αž‰αž»αŸ†αž…αž„αŸ‹αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžŸαžšαžŸαŸαžšαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž—αŸ’αž‰αŸ€αžœ NTP αžŸαžΆαž˜αž‰αŸ’αž‰αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ” αž‡αžΆαž‘αžΌαž‘αŸ… αž€αžΆαžšαžŸαž“αŸ’αž‘αž“αžΆαž“αžΉαž„αž”αŸ’αžšαŸ‚αž‘αŸ…αž‡αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž“αŸƒαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“ αž“αž·αž„αžšαž”αŸ€αž”αžŠαŸ‚αž›αž€αžΆαžšαž†αŸ’αž›αžΎαž™αžαž”αž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ NTP αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ” αž€αžΌαžŠαž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžšαžŸαŸαžšαž‡αžΆ python αž–αŸ’αžšαŸ„αŸ‡αžαžΆαž˜αž‚αŸ†αž“αž·αžαžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ† αžœαžΆαž˜αž·αž“αž˜αžΆαž“αž—αžΆαžŸαžΆαž›αŸ’αž’αž‡αžΆαž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžšαžΏαž„αž”αŸ‚αž”αž“αŸαŸ‡αž‘αŸαŸ” Connoisseurs αž“αžΉαž„αž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αž…αŸ†αž–αŸ„αŸ‡αž—αžΆαž–αžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆαž“αŸƒαž€αžΌαžŠαž‡αžΆαž˜αž½αž™αž›αŸαžαž€αžΌαžŠ ntplib - αžαŸ’αž‰αž»αŸ†αžαŸ’αžšαžΌαžœαž”αžΆαž“ "αž”αŸ†αž•αž»αžŸαž‚αŸ†αž“αž·αž" αžŠαŸ„αž™αžœαžΆαŸ”

αžŠαžΌαž…αŸ’αž“αŸαŸ‡ NTP αž‡αžΆαž’αŸ’αžœαžΈ? NTP αž‚αžΊαž‡αžΆαž–αž·αž’αžΈαž€αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„αž‡αžΆαž˜αž½αž™αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž–αŸαž›αžœαŸαž›αžΆαŸ” αž–αž·αž’αžΈαž€αžΆαžšαž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž“αŸ…αž€αŸ’αž“αž»αž„αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž‘αŸ†αž“αžΎαž”αž‡αžΆαž…αŸ’αžšαžΎαž“αŸ” αž§αž‘αžΆαž αžšαžŽαŸ សេវអ w32tm αž“αŸ…αž›αžΎ windows αŸ”

αž˜αžΆαž“ 5 αž€αŸ†αžŽαŸ‚αž“αŸƒαž–αž·αž’αžΈαž€αžΆαžš NTP αžŸαžšαž»αž”αŸ” αž‘αžΈαž˜αž½αž™ αž€αŸ†αžŽαŸ‚ 0 (1985, RFC958) αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΆαžαŸ‹αž‘αž»αž€αžαžΆαž›αŸ‚αž„αž”αŸ’αžšαžΎαž αžΎαž™αŸ” αžαŸ’αž˜αžΈβ€‹αž‡αžΆαž„β€‹αž“αŸαŸ‡β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž”αŸ’αžšαžΎβ€‹αž“αžΆβ€‹αž–αŸαž›β€‹αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“ αž‘αžΈ 1 (1988, RFC1059), αž‘αžΈ 2 (1989, RFC1119), αž‘αžΈ 3 (1992, RFC1305) αž“αž·αž„β€‹αž‘αžΈ 4 (1996, RFC2030) αŸ” αž€αŸ†αžŽαŸ‚ 1-4 αž‚αžΊαžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαž‡αžΆαž˜αž½αž™αž‚αŸ’αž“αžΆαž‘αŸ…αžœαž·αž‰αž‘αŸ…αž˜αž€ αž–αž½αž€αžœαžΆαžαž»αžŸαž‚αŸ’αž“αžΆαžαŸ‚αž“αŸ…αž€αŸ’αž“αž»αž„αž€αŸ’αž”αž½αž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ”

αž‘αž˜αŸ’αžšαž„αŸ‹αž€αž‰αŸ’αž…αž”αŸ‹

αžŸαžšαžŸαŸαžšαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž—αŸ’αž‰αŸ€αžœ NTP αžŸαžΆαž˜αž‰αŸ’αž‰

αžŸαžΌαž…αž“αžΆαž€αžšαž›αŸ„αž (αžŸαžΌαž…αž“αžΆαž€αžšαž€αŸ‚αžαž˜αŸ’αžšαžΌαžœ) αž‚αžΊαž‡αžΆαž›αŸαžαžŠαŸ‚αž›αž”αž„αŸ’αž αžΆαž‰αž–αžΈαž€αžΆαžšαž–αŸ’αžšαž˜αžΆαž“αž‘αžΈαž–αžΈαžšαž›αŸ„αžαŸ” αž’αžαŸ’αžαž“αŸαž™αŸ–

  • 0 - αž‚αŸ’αž˜αžΆαž“αž€αžΆαžšαž€αŸ‚αžαž˜αŸ’αžšαžΌαžœ
  • 1 - αž“αžΆαž‘αžΈαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž“αŸƒαžαŸ’αž„αŸƒαž˜αžΆαž“ 61 αžœαž·αž“αžΆαž‘αžΈ
  • 2 - αž“αžΆαž‘αžΈαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž“αŸƒαžαŸ’αž„αŸƒαž˜αžΆαž“ 59 αžœαž·αž“αžΆαž‘αžΈ
  • 3 - αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž”αžšαžΆαž‡αŸαž™ (αž’αžŸαŸ‹αž–αŸαž›αž’αŸ’αžœαžΎαžŸαž˜αž€αžΆαž›αž€αž˜αŸ’αž˜)

αž›αŸαžαž€αŸ†αžŽαŸ‚ (αž›αŸαžαž€αŸ†αžŽαŸ‚) - αž›αŸαžαž€αŸ†αžŽαŸ‚αž–αž·αž’αžΈαž€αžΆαžš NTP (1-4) αŸ”

αžšαž”αŸ€αž” (αžšαž”αŸ€αž”) β€” αžšαž”αŸ€αž”αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž•αŸ’αž‰αžΎαž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αŸ” αžαž˜αŸ’αž›αŸƒαž–αžΈ 0 αžŠαž›αŸ‹ 7 αžŠαŸ‚αž›αž‡αžΆαžšαžΏαž„αž’αž˜αŸ’αž˜αžαžΆαž”αŸ†αž•αž»αžαŸ–

  • 3 - αž’αžαž·αžαž·αž‡αž“
  • 4 - αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ
  • 5 - αžšαž”αŸ€αž”αž•αŸ’αžŸαžΆαž™

αžŸαŸ’αžšαž‘αžΆαž”αŸ‹ (αž€αž˜αŸ’αžšαž·αžαžŸαŸ’αžšαž‘αžΆαž”αŸ‹) - αž…αŸ†αž“αž½αž“αž“αŸƒαžŸαŸ’αžšαž‘αžΆαž”αŸ‹αž˜αž’αŸ’αž™αž˜αžšαžœαžΆαž„αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ αž“αž·αž„αž“αžΆαž‘αž·αž€αžΆαž™αŸ„αž„ (1 - αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž™αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž–αžΈαž“αžΆαž‘αž·αž€αžΆαž™αŸ„αž„, 2 - αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž™αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαžŠαŸ‚αž›αž˜αžΆαž“αž€αž˜αŸ’αžšαž·αž 1 αŸ”αž›αŸ”)
αž’αžΆαž„αž αŸ‚αž›αž‘αžΉαž€ αž‚αžΊαž‡αžΆαž…αŸ†αž“αž½αž“αž‚αžαŸ‹αžŠαŸ‚αž›αž”αžΆαž“αž…αž»αŸ‡αž αžαŸ’αžαž›αŸαžαžΆαžαŸ†αžŽαžΆαž„αž±αŸ’αž™αž…αž“αŸ’αž›αŸ„αŸ‡αž–αŸαž›αž’αžαž·αž”αžšαž˜αžΆαžšαžœαžΆαž„αžŸαžΆαžšαž‡αžΆαž”αŸ‹αž‚αŸ’αž“αžΆαŸ” αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž—αŸ’αž‰αŸ€αžœ NTP αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž…αž“αŸ’αž›αŸ„αŸ‡αž–αŸαž›αžŠαŸ‚αž›αžœαžΆαžšαŸ†αž–αžΉαž„αžαžΆαž“αžΉαž„αž’αŸ’αžœαžΎαž€αžΆαžšαžŸαŸ’αž‘αž„αŸ‹αž˜αžαž·αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ αž αžΎαž™αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ NTP αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž…αž“αŸ’αž›αŸ„αŸ‡αž–αŸαž›αžŠαŸ‚αž›αžœαžΆαžšαŸ†αž–αžΉαž„αžαžΆαž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ„αŸ‡αž†αŸ’αž“αŸ„αžαŸ” αžαž˜αŸ’αž›αŸƒαž‚αžΊαžŸαŸ’αž˜αžΎαž“αžΉαž„αž›αŸ„αž€αžΆαžšαžΈαžαž‚αŸ„αž›αž–αžΈαžšαž“αŸƒαžœαž·αž“αžΆαž‘αžΈαŸ”
αž—αžΆαž–αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹ (αž—αžΆαž–αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹) αž‚αžΊαž‡αžΆαž…αŸ†αž“αž½αž“αž‚αžαŸ‹αžŠαŸ‚αž›αž”αžΆαž“αž…αž»αŸ‡αž αžαŸ’αžαž›αŸαžαžΆαžαŸ†αžŽαžΆαž„αž±αŸ’αž™αž—αžΆαž–αžαŸ’αžšαžΉαž˜αžαŸ’αžšαžΌαžœαž“αŸƒαž“αžΆαž‘αž·αž€αžΆαž”αŸ’αžšαž–αŸαž“αŸ’αž’αŸ” αžαž˜αŸ’αž›αŸƒαž‚αžΊαžŸαŸ’αž˜αžΎαž“αžΉαž„αž›αŸ„αž€αžΆαžšαžΈαžαž‚αŸ„αž›αž–αžΈαžšαž“αŸƒαžœαž·αž“αžΆαž‘αžΈαŸ”
αž€αžΆαžšαž–αž“αŸ’αž™αžΆαž–αŸαž›αž‡αžΆ root (αž—αžΆαž–αž™αžΊαžαžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ) αž‚αžΊαž‡αžΆαž–αŸαž›αžœαŸαž›αžΆαžŠαŸ‚αž›αžœαžΆαžαŸ’αžšαžΌαžœαž€αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž“αžΆαž‘αž·αž€αžΆαžŠαžΎαž˜αŸ’αž”αžΈαž‘αŸ…αžŠαž›αŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ NTP αžŠαŸ‚αž›αž‡αžΆαž…αŸ†αž“αž½αž“αžαŸαžšαž“αŸƒαžœαž·αž“αžΆαž‘αžΈαŸ”
αž€αžΆαžšαž”αŸ‚αž€αžαŸ’αž‰αŸ‚αž€αž‡αžΆ root (αžαŸ’αž…αžΆαžαŸ‹αžαŸ’αž…αžΆαž™αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ) - αž€αžΆαžšαžαŸ’αž…αžΆαžαŸ‹αžαŸ’αž…αžΆαž™αž“αŸƒαž“αžΆαž‘αž·αž€αžΆαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ NTP αž‡αžΆαž…αŸ†αž“αž½αž“αž…αŸ†αžŽαž»αž…αžαŸαžšαž“αŸƒαžœαž·αž“αžΆαž‘αžΈαŸ”
αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž―αž€αžŸαžΆαžšαž™αŸ„αž„ (αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž”αŸ’αžšαž—αž–) - αž˜αžΎαž›αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž˜αžΆαž“ stratum 1 αž“αŸ„αŸ‡ ref id αž‚αžΊαž‡αžΆαžˆαŸ’αž˜αŸ„αŸ‡αž“αžΆαž‘αž·αž€αžΆαž’αžΆαžαžΌαž˜αž·αž€ (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)

αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‘αž·αž“αŸ’αž“αž“αŸαž™αž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ

αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‘αž·αž“αŸ’αž“αž“αŸαž™αž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž‚αžΊαžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆαž‘αŸ…αž“αžΉαž„αžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αžšαž”αžŸαŸ‹αžŸαž»αž—αžΆαž–αž”αž»αžšαžŸαž‡αž“αž‡αžΆαžαž·αž’αž„αŸ‹αž‚αŸ’αž›αŸαžŸαž–αžΈαž”αž‰αŸ’αž αžΆαž…αžΆαžŸαŸ‹αžšαž”αžŸαŸ‹ Raymond M. Smallian (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

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹