C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

NTPサーバに接続し、時刻校正したいが、複数PC不揃いになる

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■90653 / inTopicNo.1)  NTPサーバに接続し、時刻校正したいが、複数PC不揃いになる
  
□投稿者/ としお (1回)-(2019/04/01(Mon) 19:31:44)

分類:[C#] 


Visual Studio 2015 C#で時刻を更新するプログラムを作りたく、
nonsoft様のページを参考にし、
http://nonsoft.la.coocan.jp/SoftSample/CS.NET/SampleNtpDateTime.html
コードはイベントをボタンクリック→フォームロードに変えた程度でそのまま使わせていただき
「起動したら時刻更新するだけ」
というもの作りました。(管理者権限で起動します)

NTPサーバ実機 − L3 − プログラムをインストールしたPC[複数台]

という環境です。
早速各PCでプログラムを実行したところ、確かに時刻校正はされました。
しかし、各PCを比べてみると1秒未満の範囲でですが、時刻が微妙に不揃いになっており困っています。

そこそも「1秒未満程度のズレは起きうるもの」なのか、
参考にしたコードではなにか「精度を保つための処理が不足している」のか
「当方の接続機器になにか邪魔するものがある」のか
わかりません。

どうすれば複数台のPCの時刻をそろえられるのでしょうか?
よろしくお願いします。




引用返信 編集キー/
■90654 / inTopicNo.2)  Re[1]: NTPサーバに接続し、時刻校正したいが、複数PC不揃いになる
□投稿者/ shu (1171回)-(2019/04/01(Mon) 21:29:58)
No90653 (としお さん) に返信


> そこそも「1秒未満程度のズレは起きうるもの」なのか、
起こりうるものです。


リンク先だとtime.windows.comに同期となっていますが
全クライアントでその設定ということでしょうか?
なるべく近くのNTPサーバーに同期させるようにすれば改善される可能性は高いです。
また
(1) 外部NTPサーバー と LAN内NTPサーバーの同期
(2) LAN内NTPサーバー と 各クライアント
(3) 各クライアントの同期タイミングをずらす
のような対策を行えば誤差はへるかと思います。
引用返信 編集キー/
■90655 / inTopicNo.3)  Re[2]: NTPサ時刻校正したいが、複数PC不揃いになる
□投稿者/ としお (2回)-(2019/04/02(Tue) 09:24:52)
2019/04/02(Tue) 09:46:43 編集(投稿者)
2019/04/02(Tue) 09:46:40 編集(投稿者)

大変申し訳ありません。
説明を省略しすぎていました。
プログラムをインストールしたすべてのPCで「time.windows.com」を「NTPサーバ実機」のIPアドレスに変更しております。
NTPサーバは目の前にあり、L3経由で接続しています。

また、校正後の時刻の確認はWindowsPC(Windows10)の画面右下にある時計をクリックしたときに表示される時刻+カレンダーの画面の秒部分を隣のPCと比較していました。

No90654 (shu さん) に返信
> ■No90653 (としお さん) に返信
>
>
>>そこそも「1秒未満程度のズレは起きうるもの」なのか、
> 起こりうるものです。
>
>
> リンク先だとtime.windows.comに同期となっていますが
> 全クライアントでその設定ということでしょうか?
> なるべく近くのNTPサーバーに同期させるようにすれば改善される可能性は高いです。
> また
> (1) 外部NTPサーバー と LAN内NTPサーバーの同期
> (2) LAN内NTPサーバー と 各クライアント
> (3) 各クライアントの同期タイミングをずらす
> のような対策を行えば誤差はへるかと思います。
引用返信 編集キー/
■90656 / inTopicNo.4)  Re[3]: NTPサ時刻校正したいが、複数PC不揃いになる
□投稿者/ 774RR (676回)-(2019/04/02(Tue) 10:13:18)
Windows の「インターネット時刻」は Unix 系でいうところの ntpdate 相当であって xntpd ではないので
・一度時刻合わせしたら、それ以後は各自のマシンの独自時計によって勝手に計時する
・時刻合わせした瞬間には高い精度で絶対時間が一致している(はず)だが
・しばらくするとずれているのは当たり前
・ Windows 10 より古い W32Time サービスは1,2秒程度のずれは許容していた
(これを合わそうとすると CPU/ネットワーク 資源をたくさん使うため)

https://docs.microsoft.com/en-us/windows-server/networking/windows-time-service/support-boundary
によると「サーバー側が」Server 2012 R2 か Server 2016 かで精度が違う

https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc773013(v=ws.10)
ActiveDirectory に参加していると勝手に AD DS に合わせに行ってしまう。

その辺次第なのではないかな・・・と。


引用返信 編集キー/
■90658 / inTopicNo.5)  Re[4]: NTPサ時刻校正したいが、複数PC不揃いになる
□投稿者/ としお (3回)-(2019/04/02(Tue) 14:07:13)
皆様、回答ありがとうございます。
場合によって1,2秒程度のずれがあることが理解できました。
その後も対策を調べていたのですが
dobon.net様のコード
https://dobon.net/vb/dotnet/process/standardoutput.html
を参考にして、
以下の手法で一見うまくいきそうなのですが、根本的な間違いや、やってはいけない操作等がありますでしょうか?


<1>管理者権限で起動
<2>元の参考ソースの通りNTPサーバから時刻取得
<3>PC時刻を校正 ←この時点で1秒未満のズレがあることが本件の質問案件でした
<4>【w32tm /stripchart /computer:[NTPサーバ] /samples:1】をコマンド送信し、戻り値を取得

取得例)
13:47:40, d:+00.0182803s o:+00.5406896s [ |* ]

<5>o: の後に続く差分(+00.5406896)を取得し現在日時に対して差分をAddMillisecondsした値で再校正
<6>完了

再校正後例)
13:47:43, d:+00.0210491s o:+00.0011926s [ * ]

という結果でかなり差を縮めることができました。(できたように見えます)


<使ったソースの抜粋>
objSck.Send(sdat, sdat.GetLength(0), 192.168.0.10, 123);

// NTPサーバから日時データ受信
Byte[] rdat = objSck.Receive(ref ipAny);

// 1900年1月1日からの経過時間(日時分秒)
long lngAllS; // 1900年1月1日からの経過秒数
long lngD; // 日
long lngH; // 時
long lngM; // 分
long lngS; // 秒

// 1900年1月1日からの経過秒数計算
lngAllS = (long)(
rdat[40] * Math.Pow(2, (8 * 3)) +
rdat[41] * Math.Pow(2, (8 * 2)) +
rdat[42] * Math.Pow(2, (8 * 1)) +
rdat[43]);

if ((rdat[0] & 0xc0) == 0)//同期
{
Outputlog(Logging.Lv6_INFO4, Logging.Typ2_SEND, "同期受信");

// 1900年1月1日からの経過(日時分秒)計算
lngD = lngAllS / (24 * 60 * 60); // 日
lngS = lngAllS % (24 * 60 * 60); // 残りの秒数
lngH = lngS / (60 * 60); // 時
lngS = lngS % (60 * 60); // 残りの秒数
lngM = lngS / 60; // 分
lngS = lngS % 60; // 秒

// 現在の日時(DateTime)計算
DateTime dtTime = new DateTime(1900, 1, 1);
dtTime = dtTime.AddDays(lngD);
dtTime = dtTime.AddHours(lngH);
dtTime = dtTime.AddMinutes(lngM);
dtTime = dtTime.AddSeconds(lngS);

// グリニッジ標準時から日本時間への変更
dtTime = dtTime.AddHours(9);

// 現在の日時表示
System.Diagnostics.Trace.WriteLine(dtTime);

// システム時計の日時設定
Boolean ret = SetSysTime(dtTime);
if (ret == false)
{
//エラー処理
}

//Processオブジェクトを作成
System.Diagnostics.Process p = new System.Diagnostics.Process();

//ComSpec(cmd.exe)のパスを取得して、FileNameプロパティに指定
p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
//出力を読み取れるようにする
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = false;
//ウィンドウを表示しないようにする
p.StartInfo.CreateNoWindow = true;
//コマンドラインを指定("/c"は実行後閉じるために必要)

p.StartInfo.Arguments = @"/c w32tm /stripchart /computer:" + 192.168.0.10 + " /samples:1";

 //起動
p.Start();

//出力を読み取る
string results = p.StandardOutput.ReadToEnd();

//プロセス終了まで待機する
//WaitForExitはReadToEndの後である必要がある
//(親プロセス、子プロセスでブロック防止のため)
p.WaitForExit();
p.Close();
int index1 = results.IndexOf("o:+");
int index2 = results.IndexOf("s [");
//出力された結果を表示
string strms = Mid(results, index1+3, index2-2 - index1);
Double dms = 0;

double.TryParse(strms, out dms);

// 現在の日時(DateTime)計算
DateTime dtReTime = DateTime.Now.AddMilliseconds(dms * 1000);

// システム時計の再校正
Boolean ret2 = SetSysTime(dtReTime);
if (ret2 == true)
{
//エラー処理
}
}
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ