外部のサーバーから時刻を取得する【Unity】

はいどーもこんばんは、今年が平成何年なのかわからないニートです。
本日は外部のサーバーから時刻を取得する方法を備忘録がてら書いていこうと思いますよ。
参考にさせていたいた記事は以下のものです(以下「参照記事」)。
https://anz-note.ghost.io/2018/04/03/1522685769/

外部のサーバーから時刻を取得するって?

時刻を取得する方法と言えば、最も有名なのはDateTime.Nowプロパティでしょう。
これは「ローカルコンピュータの時刻を取得」します。
単に時刻が欲しいだけならこれで問題ありません。
ですが稀にローカルの設定に依存しない時刻すなわち「外部のサーバーから時刻を取得したい」場合があるのです。

どんなときに外部のサーバーから時刻を取得したくなるか?

ローカル時刻だと何が問題になるかと言えば、参照記事にも書かれていますが「放置ゲーなどでX時間後に発生するイベントを、ローカル時刻をいじることで強制的に発生させることができる」ことが特に有償ゲームだと問題になります。
「X時間戻した」ことに対する不正のチェックは簡単なのですが、「X時間進めた」ことに対する不正のチェックはローカル時刻を使用している場合は非常に難しい(というか無理?)のですね。
そこで「外部のサーバーから取得した時刻」を利用します。
外部のサーバーから取得した時刻を使用すればローカル時刻をいじっても無駄、あるいは不正チェックに外部のサーバーから取得した時刻を利用することで「X時間進めた」ことに対する不正チェックも簡単におこなえるようになります。

サーバーを用意するのは面倒

外部のサーバーから時刻を取得する際に最も問題となるのがサーバーの用意でしょう。
僕もサーバーなんて用意できませんw
なのでNICTさんが公開してくれている時刻を利用しましょう!
具体的には以下のURLになります。
https://ntp-a1.nict.go.jp/cgi-bin/time?UTC
少し時間をおいて更新すると値が変わっていることがわかると思います。

なお、他にも色々な形式のタイムスタンプが用意されています。
以下のURLからお好みのものを利用してください(参照記事ではJSON形式のものが使われています)。
http://www.nict.go.jp/JST/http.html

とりあえず時刻を取得してみる

UniRxを使った方が何かと便利っぽいので、ここでもUniRxを使ったサンプルにします。
というわけでコードをドン。

NTP_UTC_URLは読み取り専用のフィールドで、NICTさんが公開してくれている時刻のアドレスです。
これがどこで使われているのかと言えば、Startメソッド内です。
時刻の取得が成功したとき、NICTさんが公開してくれている時刻形式をC#で扱える形式に変換しています(ParseDate)。
あとは_npt_timeフィールドを何やらすればいいというわけです。

今回はエラーの処理をほとんど実装してませんが、実際のゲームに導入するときはサーバーが落ちているときなどを想定したプログラムを組んだほうがよさそうですね。

なぜUTCなのか

今回取得したのは協定世界時(UTC)ですが、これには理由があります。
僕が今回のプログラムで想定していたのは「不正に時間を進めていた場合に警告を表示する」という機能の実装です。
どのようにして「不正に時間を進めていたいた」かをチェックするかと言えば、単にローカル時刻とサーバーから取得した時刻を比較するだけです。
このとき、サーバーの時刻が日本時刻を基準に考えられていると、ローカル時刻と比較したとき何やら面倒な雰囲気がプンプンしたから(海外でゲームを実行したときの時間の比較方法とか)です。
あとはAndroidでなぜかDateTimeで取得するローカル時刻が勝手にUTCになる不具合(仕様なのかどうか知りませんけど)があったので、それも意識しました。

終わりに

外部のサーバーから時刻を取得する方法を備忘録がてらまとめてみました。
TCP/IPやらHTTPやらについてあらかじめ学んでおいたため、わりとすんなりいけました。
ただ取得したデータのパース(?)の仕方がいまいちわからなかったので(今回もゴリ押しですしw)、もう少し勉強したい感じはあります。
例えばBody部だけ取り出したりとか……。

ボチボチ頑張っていきますよ。
ほなそんな感じでまた。

フォローする