/////////////////////////////////////////////////////////
//定義
#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
|