サーバーのドメインまたはIPアドレスを入力すると時刻を取得して表示します。
「時刻」がローカルの時刻、「結果」がサーバーの時刻です。
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <time.h>
/*環境依存*/
#include <limits.h>
#if UCHAR_MAX!=0xff || UINT_MAX!=0xffffffff
#error Variable size can't accepted.
#endif
#if ULONG_MAX!=0xffffffff || ULLONG_MAX!=0xffffffffffffffff
#error Variable size can't accepted.
#endif
typedef struct {
unsigned int hidword;
unsigned int lodword;
} rybits;
typedef struct {
unsigned char seigyo;
unsigned char kaisou;/*階層*/
unsigned char bkankaku;/*ボーリング間隔*/
unsigned char seido;/*精度*/
unsigned int rdelay;/*ルート遅延*/
unsigned int rkaku;/*ルート拡散*/
unsigned int ssikibetu;/*参照識別子*/
rybits santstamp;/*参照タイムスタンプ*/
rybits kaitstamp;/*開始タイムスタンプ*/
rybits rectstamp;/*受信タイムスタンプ*/
rybits sentstamp;/*送信タイムスタンプ*/
unsigned int key;/*鍵識別子*/
rybits md[2];/*メッセージダイジェスト*/
} sntppacket;
int main(void) {
char servername[1024];
WSADATA wsa;
SOCKET sock;
SOCKADDR_IN server;
HOSTENT* host;
sntppacket sendp,recvp;
int fromsize;
int gotsize;
char filename[1025];
int i;
HANDLE fp;
DWORD writtensize;
double msec,kizyun;
SYSTEMTIME st;
unsigned int ms;
unsigned long long starttime;
unsigned long long gettime;
unsigned long long sendtime;
unsigned long long endtime;
unsigned long zikan;
time_t ttime;
struct tm* ptime;
printf("サーバー?");
scanf("%s",servername);
if(WSAStartup(MAKEWORD(1,1),&wsa)) {
printf("開始エラー\n");
return 1;
}
sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock==INVALID_SOCKET) {
printf("ソケット作成エラー");
WSACleanup();
return 1;
}
server.sin_family=AF_INET;
server.sin_port=htons(123);
server.sin_addr.s_addr=inet_addr(servername);
if(server.sin_addr.s_addr==0xFFFFFFFF) {
host=gethostbyname(servername);
if(host==0) {
if(WSAGetLastError()==WSAHOST_NOT_FOUND)
printf("サーバーが見つかりません\n");
else printf("サーバー検索エラー\n");
closesocket(sock);
WSACleanup();
return 1;
}
server.sin_addr.s_addr=*((unsigned long*)host->h_addr);
}
RtlFillMemory(&sendp,sizeof(sendp),0);
sendp.seigyo=0x0B;
sendp.sentstamp.hidword=htonl((unsigned long)time(NULL)+2208988800UL);
GetLocalTime(&st);
msec=st.wMilliseconds;
kizyun=500;
ms=0;
for(i=31;i>=0;i--) {
if(msec>=kizyun) {
ms|=1<<i;
msec-=kizyun;
}
kizyun/=2;
}
sendp.sentstamp.lodword=htonl((unsigned long)ms);
if(sendto(sock,(const char*)&sendp,sizeof(sendp),0,
(SOCKADDR*)&server,sizeof(server))==SOCKET_ERROR) {
printf("送信エラー\n");
closesocket(sock);
WSACleanup();
return 1;
}
fromsize=sizeof(server);
gotsize=recvfrom(sock,(char*)&recvp,sizeof(recvp),0,
(SOCKADDR*)&server,&fromsize);
if(gotsize==SOCKET_ERROR) {
printf("受信エラー\n");
closesocket(sock);
WSACleanup();
return 1;
}
starttime=(unsigned long long)ntohl(recvp.kaitstamp.hidword)<<32 |
(unsigned long long)ntohl(recvp.kaitstamp.lodword);
gettime=(unsigned long long)ntohl(recvp.rectstamp.hidword)<<32 |
(unsigned long long)ntohl(recvp.rectstamp.lodword);
sendtime=(unsigned long long)ntohl(recvp.sentstamp.hidword)<<32 |
(unsigned long long)ntohl(recvp.sentstamp.lodword);
endtime=((unsigned long long)time(NULL)+2208988800ULL)<<32;
GetLocalTime(&st);
msec=st.wMilliseconds;
kizyun=500;
ms=0;
for(i=31;i>=0;i--) {
if(msec>=kizyun) {
ms|=1<<i;
msec-=kizyun;
}
kizyun/=2;
}
endtime|=(unsigned long long)ms;
sendtime+=((endtime-starttime)-(sendtime-gettime))/2;
ttime=(time_t)(sendtime>>32)-2208988800UL;
zikan=(unsigned int)(sendtime & 0xffffffff);
msec=0;
kizyun=500;
for(i=31;i>=0;i--) {
if(zikan & (1<<i))msec+=kizyun;
kizyun/=2;
}
ms=(unsigned int)msec;
for(i=0;;i++) {
wsprintf(filename,"gotdata\\gotdata%04d.ntp",i);
fp=CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,0);
if(fp!=INVALID_HANDLE_VALUE)break;
}
WriteFile(fp,&recvp,gotsize,&writtensize,NULL);
CloseHandle(fp);
closesocket(sock);
WSACleanup();
printf("正常終了\n");
ptime=localtime(&ttime);
printf("時刻:%d年%d月%d日%d時%d分%d秒%d\n",
st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
printf("結果:%d年%d月%d日%d時%d分%d秒%d\n",
ptime->tm_year+1900,ptime->tm_mon+1,ptime->tm_mday,
ptime->tm_hour,ptime->tm_min,ptime->tm_sec,ms);
return 0;
}
NTPサーバ一覧
http://www.venus.dti.ne.jp/~yoshi-o/NTP/NTP-Table.html
でも、ほぼ自分ばっかり投稿しているなあ...