goo blog サービス終了のお知らせ 
goo

NTPによる時刻取得

◆一覧リスト
HSP Ver3.0
HSP Ver2.61
ブログ関連
その他
★人気blogランキング

「NTPによる時刻取得」
NTP(Network Time Protocol)
ネットワークを介して時刻調整をするプロトコル。
サーバは、GPSや原子時計等を利用して正確な時刻を取得しています。

ポートは、123でUDPを使用。

使用例
Ws2_32.dllを使用します。
  1. 「WSAStartup」で通信の初期化
  2. 「socket」でソケット作成
  3. 「inet_addr」「gethostbyname」でホスト情報取得
  4. 「connect」で接続
  5. 「WSAAsyncSelect」で非同期通信
  6. 「send」で、NTP_Packetを送信
    最初の4バイトに、数値11を指定。他は0。
  7. 「recv」で、NTP_Packetを受信
  8. 「WSAAsyncSelect」で非同期終了
  9. 「shutdown」で、送受信を停止
  10. 「closesocket」でソケット解放
  11. 「WSACleanup」でリソース解放

NTP_Packet (48Byte)
位置長さ名称説明
02bitLI
閏秒指示子
閏秒の分について
0:警告なし
1:最後の分は61秒
2:最後の分は59秒
3:同期していない
2bit3bitVN
バージョン番号
バージョン番号
3:NTPサーバ(IPv4)
4:SNTPサーバ(IPv4 IPv6)
5bit3bitmode
モード
モード
3:クライアント
4:サーバ
8bit8bitStratum
階級
ローカル時計の階級
0:既定なし
1:一次基準源(GPS等)
2-15:NTPやSNTP経由
16-255:予約済み
16bit8bitPoll
ポーリング間隔
連続するメッセージ間の最大間隔
(2のべき乗の秒数)
24bit8bitPrecision
精度
時刻の精度
(2のべき乗の秒数)
4Byte4byteRoot Delay
ルート遅延
一次基準源までの往復の遅延の合計秒
15bit-16bitに少数値
8Byte4ByteRoot Dispersion
ルート分散
一次基準源との誤差秒数
15bit-16bitに少数値
12Byte4ByteReference Identifier
基準ID
IPアドレス、又は文字列
16Byte8ByteReference Timestamp
基準タイムスタンプ
現在時間
24Byte8ByteReceive Timestamp
受信タイムスタンプ
サーバに要求が届いた時間
32Byte8ByteTransmit Timestamp
送信タイムスタンプ
サーバからクライアントに送られた時間
40Byte4Bytetransmit_timestamp_secondsローカルタイム
44Byte4Bytetransmit_timestamp_fractionsミリセカンド


サンプル
NTPを使用して、5秒ごとに時刻を取得して表示しています。
/////////////////////////////////////////////////////////
//定義
#define PORT		123
#define SOCK_DGRAM		2
#define AF_INET		2

//FD_READ(0x01) FD_WRITE(0x02) FD_CONNECT(0x10) FD_CLOSE(0x20)
#define FD_MESSAGE		0x33
#define FD_EVENT		0x5000

#define	WM_TIMER		0x0113
#define WM_CLOSE		0x0010
#define ID_TIMER		0x6000

/////////////////////////////////////////////////////////
//関数の登録
#uselib "Ws2_32.dll"
	#cfunc WSAStartup     "WSAStartup"     int , sptr
	#cfunc socket         "socket"         int,int,int
	#cfunc inet_addr      "inet_addr"      sptr
	#cfunc gethostbyname  "gethostbyname"  sptr
	#cfunc connect        "connect"        int,sptr,int
	#cfunc send           "send"           int,sptr,int,int
	#cfunc recv           "recv"           int,sptr,int,int
	#cfunc WSAAsyncSelect "WSAAsyncSelect" int,int,int,int
	#func  shutdown       "shutdown"       int,int
	#func  closesocket    "closesocket"    int
	#func  WSACleanup     "WSACleanup"
	#cfunc WSAGetLastError "WSAGetLastError"
	#cfunc htons "htons" int
	#cfunc ntohl "ntohl" int

#uselib "crtdll.dll"
	#func  time      "time" sptr
	#cfunc localtime "localtime" sptr
	#cfunc asctime   "asctime" sptr

#uselib "kernel32.dll"
	#func SetLocalTime "SetLocalTime" sptr

#uselib "user32.dll"
	#cfunc SetTimer  "SetTimer" int,int,int,sptr
	#cfunc KillTimer "KillTimer" int,int

/////////////////////////////////////////////////////////
//メイン
	screen 0,300,120
	title "NTP サンプル":font "",12
	color : boxf : color 255,255,255
	sdim host,260
	sdim hostname,260
	dim  tflag : tflag=0
	host="eric.nc.u-tokyo.ac.jp"
	hostname=host
	pos 0,0:input host,250,20
	pos 250,0:objsize 50,20
	button gosub "変更",*hostchange
	pos 0,20 :objsize 300,20
	button gosub "時刻設定",*SetTime

	/////////////////////////////////////////////////
	//初期化
	sdim WSAData,400
	ret=WSAStartup(0x0101, varptr(WSAData))
	if ret!=0{
		gosub *closesoc
		dialog "WSAStartup error",,"stop"
		stop
	}

	/////////////////////////////////////////////////
	//サーバーに接続
	gosub *SVconnect

	/////////////////////////////////////////////////
	//Window メッセージ
	oncmd gosub *FDEVENT,FD_EVENT
	oncmd gosub *closesoc,WM_CLOSE
	oncmd gosub *TIMER,WM_TIMER
stop

/////////////////////////////////////////////////////////
//WSAAsyncSelect
*FDEVENT
	/////////////////////////////////////////////////
	//最初に作成したsocのメッセージの場合
	if wparam==soc{
		/////////////////////////////////////////
		//lparam上位ワードが0以外ではエラー
		if lparam>>16==0{
			/////////////////////////////////
			//ret:lparam下位ワード(メッセージの種類)
			ret=lparam&0xffff
			switch ret
				/////////////////////////////////
				//recv
				case 0x0001	//FD_READ
					gosub *SVrecv
				swbreak
				/////////////////////////////////
				//closesocket
				case 0x0020	//FD_CLOSE
					gosub *closesoc
				swbreak

				/////////////////////////////////
				//デフォルト
				default
				swbreak
			swend
		}
	}
return

/////////////////////////////////////////////////////////
//ソケット作成
*SVsocket
	/////////////////////////////////////////////////
	//ソケットの作成 UDP
	soc=socket(AF_INET, SOCK_DGRAM, 0)
	if soc == 0{
		gosub *closesoc
		dialog "socket error",,"stop"
		stop
	}
return

/////////////////////////////////////////////////////////
//サーバーに接続
*SVconnect
	/////////////////////////////////////////////////
	//ソケット作成
	gosub *SVsocket

	/////////////////////////////////////////////////
	//サーバーアドレス取得
	dim  svaddr
	sdim hostent, 16
	svaddr=inet_addr(varptr(hostname))

	if svaddr==-1{
		ret=gethostbyname(varptr(hostname))
		if ret{
			dupptr svaddr,ret+12,4
			dupptr ret,svaddr,4
			dupptr svaddr,ret,4
		}
		else{
			gosub *closesoc
			dialog "gethostbyname error"
			return
		}
	}
	/////////////////////////////////////////////////
	//接続
	sdim sockaddr, 16
	wpoke sockaddr, 0, AF_INET
	wpoke sockaddr, 2, htons(PORT)
	lpoke sockaddr, 4, svaddr
	if connect(soc, varptr(sockaddr), 16)==-1{
		gosub *closesoc
		dialog "connect error"
		return
	}

	/////////////////////////////////////////////////
	//非同期通信
	ret=WSAAsyncSelect(soc,hwnd,FD_EVENT,FD_MESSAGE)
	if ret!=0:dialog "WSAAsyncSelect error",,"stop":stop

	/////////////////////////////////////////////////
	//タイマー
	ret=SetTimer(hwnd,ID_TIMER,5000,0)
return


/////////////////////////////////////////////////////////
//送信
*SVsend
	/////////////////////////////////////////////////
	//送信
	dim NTP_SEND, 12
	NTP_SEND(0) = 11;htonl(0x0B000000)
	ret=send(soc,varptr(NTP_SEND),48)
	if ret != 48{
		gosub *closesoc
		dialog "send error"
		return
	}
return

/////////////////////////////////////////////////////////
//受信と時刻表示
*SVrecv
	dim NTP_RECV , 12
	if recv(soc, varptr(NTP_RECV) ,48 ,0)==48{
		dim t
		dim tm,9

		redraw 0
		color :boxf 0,40:color 255,255,255
		ret=ntohl(NTP_RECV(10))-2208988800
		dupptr tm,localtime(varptr(ret)),36

		pos 50,50:tm(5)+=1900:tm(4)++
		if tflag==1{
			sdim systime,16
			wpoke systime,0,tm(5):wpoke systime,2,tm(4)
			wpoke systime,6,tm(3):wpoke systime,8,tm(2)
			wpoke systime,10,tm(1):wpoke systime,12,tm(0)
			SetLocalTime(varptr(systime))
			tflag=0
		}

		mes "NTP時刻"
		mes strf("%02d/",tm(5))+strf("%02d/",tm(4))+strf("%02d",tm(3))
		mes strf("%02d:",tm(2))+strf("%02d:",tm(1))+strf("%02d",tm(0))
		time varptr(t)
		lag=t-ret
		ret=localtime(varptr(t))
		dupptr tm,ret,36
		pos 200,50:tm(5)+=1900:tm(4)++
		mes "現在時刻"
		mes strf("%02d/",tm(5))+strf("%02d/",tm(4))+strf("%02d",tm(3))
		mes strf("%02d:",tm(2))+strf("%02d:",tm(1))+strf("%02d",tm(0))
		pos 50,100
		mes "時刻差 : "+ lag +" 秒"
		redraw 1
	}
return

/////////////////////////////////////////////////////////
//タイマー
*TIMER
	gosub *SVsend
return

/////////////////////////////////////////////////////////
//ホスト変更
*hostchange
	/////////////////////////////////////////////////
	//変更無しの場合
	if hostname==host:return
	hostname=host

	gosub *closesoc
	gosub *SVconnect
return

/////////////////////////////////////////////////////////
//時刻設定
*SetTime
	tflag=1
	gosub *SVsend
return

/////////////////////////////////////////////////////////
//通信終了
*closesoc
	ret=KillTimer(hwnd,ID_TIMER)
	shutdown soc,2
	ret=WSAAsyncSelect(soc,hwnd,0,0)
	closesocket soc
return

/////////////////////////////////////////////////////////
//終了
*CLOSE
	gosub *closesoc
	WSACleanup
return
コメント ( 0 ) | Trackback ( 0 )
« NTPによる時刻... ファイルのド... »
 
コメント(10/1 コメント投稿終了予定)
 
コメントはありません。
コメントを投稿する
 
名前
タイトル
URL
コメント
コメント利用規約に同意の上コメント投稿を行ってください。

数字4桁を入力し、投稿ボタンを押してください。