NTPの仕組みを調べてみた
PowershellでNTPサーバを書きたい衝動に駆られたので、NTPプロトコルについて調べてみました。
時刻同期の仕組み
- クライアントがNTPサーバにリクエスト①を送信します。また、クライアントはこのときに送信時刻t1を記録しておきます。
- NTPサーバがクライアントからのリクエスト①を受信します。また、サーバはこのときに受信時刻t2を記録しておきます。
- NTPサーバがクライアントへレスポンス②を返します。レスポンスにはリクエスト受信時刻t2とレスポンスを送信した時刻t3が含まれています。
- クライアントがNTPサーバからのレスポンス②を受信します。また、クライアントはこのときに受信時刻t4を記録しておきます。
- クライアントはリクエスト送信からレスポンス受信までにかかった時間(t4-t1)からサーバ側の処理時間(t3-t2)を引き2で割ることで、通信の片道にかかった時間を算出します。
- クライアントはt1+"5で算出した時間"とt2を比較することで、NTPサーバと自身のクロックのズレを認識することができます。
つまるところ、NTPサーバの処理はt2とt3をクライアントに返すだけでクライアントより簡単そう。 ただし、時刻同期の精度はt2とt3の時刻をどれだけ正確に計測できるかに左右されるので、オーバーヘッドの大きいPowershellで追及するのは困難。
パケットのフォーマット
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---+-----+-----+---------------+---------------+---------------+ 0|LI | Ver |Mode | Stratum |PollingInterval| Precision | +---+-----+-----+---------------+---------------+---------------+ 1| RootDelay | +---------------------------------------------------------------+ 2| RootDispersion | +---------------------------------------------------------------+ 3| ReferenceID | +---------------------------------------------------------------+ 4| ReferenceTimestamp | 5| | +---------------------------------------------------------------+ 6| OriginTimestamp | 7| | +---------------------------------------------------------------+ 8| ReceiveTimestamp | 9| | +---------------------------------------------------------------+ 0| TransmitTimestamp | 1| | +---------------------------------------------------------------+
Leap Indicator (LI)
2bitの値でうるう秒があるときはこの辺をいじるらしい。 うるう秒の検証をしたいときに使えるかも。
Version number (Ver)
NTPのバージョンを3bitで表します。3なら0b011
、4なら0b100
ですが、正直違いはよく分かっていません。
Mode
3bitの値でクライアントが送信する際には0b011
、サーバが応答する際には0b100
をセットします。
Peer Clock Stratum (Stratum)
Stratumを8bitで指定します。
Peer Polling Interval (PollingInterval)
クライアントがNTPサーバを見に行く間隔を8bitで指定するようです。
Perr Clock Precision (Precision)
ローカルのクロックの精度を8bitで表します。
Root Deley
Strarum 1までの往復の遅延を32bitで表します。
Root Dispersion
Strarum 1までの誤差を32bitで表す。
Reference ID
時刻参照先サーバのIPアドレス。
Reference Timestamp
ローカルのクロックが最後に時刻同期した時間を64bitで表します。フォーマットは後述。
Orgin Timestamp
クライアントがNTPサーバにリクエストを送信した時刻(上記t1)を64bitで表します。フォーマットは後述。
Receive Timestamp
NTPサーバがクライアントからのリクエストを受信した時刻(上記t2)を64bitでセットします。
Transmit Timestamp
パケットを送信した時刻(上記t3)を64bitでセットします。フォーマットは後述。
64bitの時刻フォーマット
NTPプロトコルでは時刻を1900年1月1日0時0分0秒からの経過秒数を64bit符号なし固定小数点で表現します。上位32bitが整数部、下位32bitが小数点以下となります。 UTCです。
参考サイト
Yoshi's Memo 「NTP (タイム)サーバ のメモ」->「NTP、SNTP のフォーマット」