NTPで時刻を同期する

Post to Google Buzz
このエントリーをはてなブックマークに追加
はてなブックマーク - NTPで時刻を同期する
Share on Facebook

Netduino PlusでNTP(SNTP)を使ってネットワーク時刻を取得するクラスを作った。また、マイコン自体のシステム時刻も同期させることができる。

こちらのサイトのおかげ。
Wrong DateTime on .NET Micro Framework Devices – Michael’s Blog

使うときはこんな感じ。

NtpClient ntp = new NtpClient { Server = "host" };
ntp.SetLocalTime();

Get() でサーバーから時刻が得られる。日本用に+9時間してあるので、他のタイムゾーンでは適宜変更する。

SetLocalTime() で取得した時刻を勝手にシステム時刻に設定する。たぶん起動時にやればよい。一応定期的に同期するためのTimerやメソッドも追加した。

ソースコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
using Microsoft.SPOT;
using System.Net;
using System.Net.Sockets;
using Microsoft.SPOT.Hardware;
using System.Threading;

namespace Netduinist.Net
{
///

<summary> /// NTP サーバーから時刻を取得したり、定期的にシステム時刻を同期します。
/// </summary>

&nbsp;

public class NtpClient
{
///

<summary> /// NTP サーバーのホスト名もしくは IP アドレスを指定します。
/// </summary>

&nbsp;

public string Server { get; set; }

private Timer syncTimer;

///

<summary> /// NtpClient クラスのインスタンスを初期化します。
/// </summary>

&nbsp;

public NtpClient()
{
Server = "ntp.nict.jp";
}

///

<summary> /// NTP サーバーから現在時刻を受信します。
/// </summary>

&nbsp;

///
public DateTime Get()
{
IPAddress address = Dns.GetHostEntry(this.Server).AddressList[0];

var ep = new IPEndPoint(address, 123);

Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.Connect(ep);

byte[] ntpData = new byte[48]; // RFC 2030
ntpData[0] = 0x1B;
for (int i = 1; i &lt; 48; i++)
{
ntpData[i] = 0;
}

try
{
s.Send(ntpData);
s.Receive(ntpData);
}
catch
{
Debug.Print("Error on NtpClient.Get");
s.Close();
throw;
}

byte offsetTransmitTime = 40;
ulong intpart = 0;
ulong fractpart = 0;
for (int i = 0; i {
intpart = 256 * intpart + ntpData[offsetTransmitTime + i];
}
for (int i = 4; i {
fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];
}

ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);

s.Close();

TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);
DateTime dateTime = new DateTime(1900, 1, 1);
dateTime += timeSpan;

DateTime networkDateTime = dateTime.AddHours(9); //
return networkDateTime;
}

///

<summary> /// NTP サーバーから現在時刻を受信し、システム時刻にセットします。
/// </summary>

&nbsp;

public bool SetLocalTime()
{
try
{
var datetime = Get();
Utility.SetLocalTime(datetime);
return true;
}
catch (Exception)
{
return false;
}
}

///

<summary> /// 同期間隔 [h] を指定して、時刻同期を開始します。同期間隔は1時間~1年未満の値を時単位で指定してください。
/// </summary>

&nbsp;

public void StartSync(int syncInterval)
{
if (syncInterval &lt; 1) syncInterval = 1; else if (syncInterval &gt; 24 * 356) syncInterval = 24 * 356;

syncTimer = new Timer(new TimerCallback((o) =&gt;
{
SetLocalTime();
}), null, 0, syncInterval * 3600);
}

///

<summary> /// 時刻同期を停止します。
/// </summary>

&nbsp;

public void StopSync()
{
if (syncTimer != null)
{
syncTimer.Dispose();
}
}

~NtpClient()
{
StopSync();
}
}
}

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>