網絡時間驗證
#命名InitSock.h
#include <winsock2.h>
#pragma comment(lib, "WS2_32") // 鏈接到WS2_32.lib
class CInitSock
{
public:
CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
{
// 初始化WS2_32.dll
WSADATA wsaData;
WORD sockVersion = MAKEWORD(minorVer, majorVer);
if(::WSAStartup(sockVersion, &wsaData) != 0)
{
exit(0);
}
}
~CInitSock()
{
::WSACleanup();
}
};
#命名XX.cpp
#include "InitSock.h"
#include <stdio.h>
CInitSock initSock;
#include <iostream>
#include <ctime>
using namespace std;
int ret_year()
{
// 基于當前系統的當前日期/時間
time_t now = time(0);
tm *ltm = localtime(&now);
int year1 = 1900 + ltm->tm_year;
int month1 = 1 + ltm->tm_mon;
int day1 = ltm->tm_mday;
return year1*10000+month1*100+day1*1;
}
int SetTimeFromTP(ULONG ulTime) // 根據時間協議返回的時間設置系統時間
{
// Windows文件時間是一個64位的值,它是從1601年1月1日中午12:00到現在的時間間隔,
// 單位是1/1000 0000秒,即1000萬分之1秒(100-nanosecond )
FILETIME ft;
SYSTEMTIME st;
// 首先將基準時間(1900年1月1日0點0分0秒0毫秒)轉化為Windows文件時間
st.wYear = 1900;
st.wMonth = 1;
st.wDay = 1;
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;
st.wMilliseconds = 0;
SystemTimeToFileTime(&st, &ft);
// 然后將Time Protocol使用的基準時間加上以及逝去的時間,即ulTime
LONGLONG *pLLong = (LONGLONG *)&ft;
//cout<<*pLLong<<endl;
// 注意,文件時間單位是1/1000 0000秒,即1000萬分之1秒(100-nanosecond )
*pLLong = *pLLong + (LONGLONG)10000000 * ulTime;
//LONGLONG *pLLong1 = (LONGLONG)10000000 * ulTime;
// 再將時間轉化回來,更新系統時間
FileTimeToSystemTime(&ft, &st);
//printf("\n獲取的網絡時間為:%04d %02d %02d %02d:%02d:%02d\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
return st.wYear*10000+st.wMonth*100+st.wDay*1;
//SetSystemTime(&st);
//cout<<*pLLong<<endl;
}
int main()
{
int flag_can_use = 0;
// 基于當前系統的當前日期/時間
int year1 = ret_year();
// 輸出 tm 結構的各個組成部分
cout << "本地電腦日期(格式:yyyymmdd): "<< year1 << endl;
SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(s == INVALID_SOCKET)
{
printf(" Failed socket() \n");
return 0;
}
// 填寫遠程地址信息,連接到時間服務器
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(37);
// 這里使用的時間服務器是129.132.2.21,更多地址請參考http://tf.nist.gov/service/its.htm
servAddr.sin_addr.S_un.S_addr = inet_addr("255.255.255.255");
if(::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)
{
printf(" Failed connect() \n");
flag_can_use =0;
cout<<"注意:如果不連接互聯網,資源無法使用!"<<"flag_can_use="<<flag_can_use<<endl;
return 0;
}
// 等待接收時間協議返回的時間。學習了Winsock I/O模型之后,最好使用異步I/O,以便設置超時
ULONG ulTime = 0;
int nRecv = ::recv(s, (char*)&ulTime, sizeof(ulTime), 0);
if(nRecv > 0)
{
ulTime = ntohl(ulTime);
SetTimeFromTP(ulTime);
//printf("成功與時間服務器的時間同步!\n");
// 基于當前系統的當前日期/時間
int year2 = SetTimeFromTP(ulTime);
cout << "網絡時間對應的日期(格式:yyyymmdd): "<< year2 << endl;
if (year2>year1)
{
int flag_can_use = 0;
cout<<"注意:本電腦的系統日期已被人為惡意修改過,資源無法使用!"<<"flag_can_use="<<flag_can_use<<endl;
}
// 輸出 tm 結構的各個組成部分
}
else
{
printf(" 時間服務器不能確定當前時間!\n");
int flag_can_use = 0;
}
::closesocket(s);
return 0;
}