āĻāĻ•āϟāĻŋ āϏāĻžāϧāĻžāϰāĻŖ NTP āĻ•ā§āϞāĻžāϝāĻŧ⧇āĻ¨ā§āϟ āϞ⧇āĻ–āĻž

āĻšā§āϝāĻžāϞ⧋ āĻšā§āϝāĻžāĻŦā§āϰāĻžāϏāĻžāĻ°ā§āϏāĨ¤ āφāϜ āφāĻŽāĻŋ āφāĻĒāύāĻžāϰ āύāĻŋāĻœā§‡āϰ āϏāĻšāϜ NTP āĻ•ā§āϞāĻžāϝāĻŧ⧇āĻ¨ā§āϟ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āϞāĻŋāĻ–āϤ⧇ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻ•āĻĨāĻž āĻŦāϞāϤ⧇ āϚāĻžāχ. āĻŽā§‚āϞāϤ, āĻ•āĻĨā§‹āĻĒāĻ•āĻĨāύāϟāĻŋ āĻĒā§āϝāĻžāϕ⧇āĻŸā§‡āϰ āĻ—āĻ āύ āĻāĻŦāĻ‚ NTP āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻĨ⧇āϕ⧇ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻ•āϰāĻž āĻšāϝāĻŧ āϤāĻžāϰ āĻĻāĻŋāϕ⧇ āĻĢāĻŋāϰ⧇ āϝāĻžāĻŦ⧇āĨ¤ āϕ⧋āĻĄāϟāĻŋ āĻĒāĻžāχāĻĨāύ⧇ āϞ⧇āĻ–āĻž āĻšāĻŦ⧇, āĻ•āĻžāϰāĻŖ, āφāĻŽāĻžāϰ āĻŽāϤ⧇, āĻāχ āϧāϰāύ⧇āϰ āϜāĻŋāύāĻŋāϏ⧇āϰ āϜāĻ¨ā§āϝ āφāϰ āϕ⧋āύ āĻ­āĻžāϞ⧋ āĻ­āĻžāώāĻž āύ⧇āχāĨ¤ Connoisseurs ntplib āϕ⧋āĻĄā§‡āϰ āϏāĻžāĻĨ⧇ āϕ⧋āĻĄā§‡āϰ āĻŽāĻŋāϞ⧇āϰ āĻĻāĻŋāϕ⧇ āĻŽāύ⧋āϝ⧋āĻ— āĻĻ⧇āĻŦ⧇āύ - āφāĻŽāĻŋ āĻāϟāĻŋ āĻĻā§āĻŦāĻžāϰāĻž "āĻ…āύ⧁āĻĒā§āϰāĻžāĻŖāĻŋāϤ" āĻšāϝāĻŧ⧇āĻ›āĻŋāĨ¤

āϤāĻžāχ NTP āĻ•āĻŋ āϝāĻžāχāĻšā§‹āĻ•? NTP āĻšāϞ āϏāĻŽāϝāĻŧ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇āϰ āϏāĻžāĻĨ⧇ āϝ⧋āĻ—āĻžāϝ⧋āϗ⧇āϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻĒā§āϰ⧋āĻŸā§‹āĻ•āϞāĨ¤ āĻāχ āĻĒā§āϰ⧋āĻŸā§‹āĻ•āϞ āĻ…āύ⧇āĻ• āφāϧ⧁āύāĻŋāĻ• āĻŽā§‡āĻļāĻŋāύ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧāĨ¤ āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āωāχāĻ¨ā§āĻĄā§‹āĻœā§‡āϰ w32tm āĻĒāϰāĻŋāώ⧇āĻŦāĻžāĨ¤

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 āϏāĻžāĻ°ā§āĻ­āĻžāϰ āϏ⧇āχ āĻŦāĻŋāϰāϤāĻŋāϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ•āϰ⧇ āϝ⧇āĻ–āĻžāύ⧇ āĻāϟāĻŋ āĻĒā§‹āϞ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒā§āϰāĻ¤ā§āϝāĻžāĻļāĻž āĻ•āϰ⧇āĨ¤ āĻŽāĻžāύāϟāĻŋ āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻŦāĻžāχāύāĻžāϰāĻŋ āϞāĻ—āĻžāϰāĻŋāĻĻāĻŽā§‡āϰ āϏāĻŽāĻžāύāĨ¤
āĻ¸ā§āĻĒāĻˇā§āϟāϤāĻž (āύāĻŋāĻ°ā§āϭ⧁āϞāϤāĻž) āĻšāϞ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻŦāĻžāĻ•ā§āώāϰāĻŋāϤ āĻĒā§‚āĻ°ā§āĻŖāϏāĻ‚āĻ–ā§āϝāĻž āϝāĻž āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ āϘāĻĄāĻŧāĻŋāϰ āύāĻŋāĻ°ā§āϭ⧁āϞāϤāĻžāϰ āĻĒā§āϰāϤāĻŋāύāĻŋāϧāĻŋāĻ¤ā§āĻŦ āĻ•āϰ⧇āĨ¤ āĻŽāĻžāύāϟāĻŋ āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻŦāĻžāχāύāĻžāϰāĻŋ āϞāĻ—āĻžāϰāĻŋāĻĻāĻŽā§‡āϰ āϏāĻŽāĻžāύāĨ¤
āĻŽā§‚āϞ āĻŦāĻŋāϞāĻŽā§āĻŦ (āϏāĻžāĻ°ā§āĻ­āĻžāϰ āϞ⧇āĻŸā§‡āĻ¨ā§āϏāĻŋ) āĻšāϞ āĻāύāϟāĻŋāĻĒāĻŋ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇ āĻĒ⧌āρāĻ›āϤ⧇ āϘāĻĄāĻŧāĻŋāϰ āϏāĻŽāϝāĻŧ āϞāĻžāϗ⧇, āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ-āĻŦāĻŋāĻ¨ā§āĻĻ⧁ āϏāĻ‚āĻ–ā§āϝāĻž āĻšāĻŋāϏāĻžāĻŦ⧇āĨ¤
āĻŽā§‚āϞ āĻŦāĻŋāĻšā§āϛ⧁āϰāĻŖ (āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻ¸ā§āĻ•ā§āϝāĻžāϟāĻžāϰ) - āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ-āĻŦāĻŋāĻ¨ā§āĻĻ⧁ āϏāĻ‚āĻ–ā§āϝāĻž āĻšāĻŋāϏāĻžāĻŦ⧇ 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 * āĻĒā§āϰāĻžāĻĒā§āϤāĻŋ - 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

āĻāĻ•āϟāĻŋ āĻŽāĻ¨ā§āϤāĻŦā§āϝ āϜ⧁āĻĄāĻŧ⧁āύ