📄 sntp.c
字号:
/*
Copyright (c) 2008-7 by zcshev in 910 room of 211 building
All rights reserved.
*/
// sntp.c : Defines the entry point for the console application.
#include "stdio.h"
#include "sntp.h"
#include "winsock.h"
#include "winbase.h"
#include "NtpTime.h"
#include "time.h"
#include "math.h"
#include "datatype.h"
#define ERROR_SOCKET 3 //get socket error
#define ERROR_SOCKET_ADD 4 //get host address error
#define ERROR_NOT_SEND 5 //send packet error
SOCKET m_hSocket;
int bSynchroniseClock;
// Tidy up prior to returning
long get_last_error()
{
#ifdef WIN32
return get_last_error();
#else
return xxx_error(); //这里是调用其他平台上的报错函数。
#endif
}
long set_last_error(dwerror)
{
#ifdef WIN32
return SetLastError(dwerror);
#else
return yyy_error(dwerror); //这里是调用其他平台上的报错函数。
#endif
}
int IsReadible(int bReadible, ulong dwTimeout)
{
struct timeval timeout;
struct fd_set fds;
int nStatus;
timeout.tv_sec = dwTimeout / 1000;
timeout.tv_usec = dwTimeout % 1000;
FD_ZERO(&fds);
FD_SET(m_hSocket, &fds);
nStatus = select(0, &fds, NULL, NULL, &timeout);
if (nStatus == SOCKET_ERROR)
return FALSE;
else
{
bReadible = !(nStatus == 0);
return TRUE;
}
}
// must have been created first
int Send(char * pszBuf, int nBuf) //Send((char *) &nbi, nSendSize) -real para
{
int rc=0;
assert(m_hSocket != INVALID_SOCKET);
rc=send(m_hSocket, pszBuf, nBuf, 0);//client use send to request
//m_hSocket-socket descriptor,pszBuf-data address to be send,nBuf-data length,0-bit sign for controling transmit
return ( rc!= SOCKET_ERROR);
}
// must have been created first
int Receive(char * pszBuf, int nBuf)
//Receive((char *) & nfp, nReceiveSize)
{
assert(m_hSocket != INVALID_SOCKET);
return recv(m_hSocket, pszBuf, nBuf, 0); //recv get the data arrived the socket,copy to user's buffer
//m_hSocket-socket descriptor, pszBuf-specify the buffer address, nBuf-buffer length, 0-bit sign for controling receive
}
void Close()
{
if (m_hSocket != INVALID_SOCKET)
{
assert(SOCKET_ERROR != closesocket(m_hSocket));
m_hSocket = INVALID_SOCKET;
}
}
///////////////////////////////////////////////////////////////
int sntp_client(char *lpszAscii)
{
SOCKADDR_IN sockAddr; // struct SOCKADDR_IN sockAddr;
char *pszBuf;
int nBuf;
SOCKADDR *lpSockAddr; //define sockaddr in winsock
int nSockAddrLen;
int nPort = 123;
int nSendSize;
ulong dwError;
int bReadable;
int nConnect;
double d;
char *pszHostName;
int nReceiveSize;
ulong RoundTripDelay=0;
ulong LocalClockOffset=0;
int button=0;
NtpBasicInfo nbi; // Initialise the NtpBasicInfo packet
NtpFullPacket nfp;
NtpServerResponse response;
SYSTEMTIME st1 ,st2 ,st3 ,st4;
m_dwTimeout = 5000;
m_hSocket = socket(AF_INET, SOCK_DGRAM, 0); // SOCK_DGRAM,using UDP
if (m_hSocket == INVALID_SOCKET)
{
printf(("Failed to create client socket, get_last_error returns: %d\n"), get_last_error());
return ERROR_SOCKET;
}
// Determine if the address is in dotted notation
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons((short) nPort); // host to network byte order
sockAddr.sin_addr.s_addr = inet_addr(lpszAscii); //copy server address to sin_addr
// If the address is not dotted notation(xxx.xxx.xxx.xxx), then do a DNS
// lookup of it.
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpszAscii); //map host name to IP address,allowing for dotted decimal
if (lphost != NULL)
sockAddr.sin_addr.s_addr =((LPIN_ADDR) lphost->h_addr)->s_addr;
else
return ERROR_SOCKET_ADD;
}
//Call the protected version which takes an address
//in the form of a standard C style struct.
nConnect = connect(m_hSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr));
//Connect to the SNTP server
if(nConnect==-1)
{
printf(("Could not connect to the SNTP server %s on port %d, get_last_error returns: %d\n"), pszHostName, nPort, get_last_error());
//Tidy up prior to returning
dwError = get_last_error();
set_last_error(dwError);
return FALSE;
}
else
{
nSendSize = sizeof(NtpBasicInfo);
memset(&nbi, 0, nSendSize);
nbi.m_LiVnMode = 27; // Encoded representation which represents
// NTP Client Request & NTP version 3.0
// LI 00 no warning VN 011 version3-only IPv4 MODE 011 3 client
nbi.m_TransmitTimestamp = myGetCurrentTime();
//nbi.m_OriginateTimestamp= myGetCurrentTime();
//Send off the NtpBasicInfo packet
if (!Send((char *) &nbi, nSendSize))
{
printf(("Failed in call to send NTP request to the SNTP server, get_last_error returns %d\n"), get_last_error());
//Tidy up prior to returning
dwError = get_last_error();
set_last_error(dwError);
return FALSE;
}
if (!IsReadible(bReadable, m_dwTimeout) || !bReadable)
{
printf(("Unable to wait for NTP reply from the SNTP server, get_last_error returns %d\n"), WSAETIMEDOUT);
set_last_error(WSAETIMEDOUT);
return FALSE;
}
response.m_DestinationTime = myGetCurrentTime();
// read back the response into the NtpFullPacket struct
nReceiveSize = sizeof(NtpFullPacket);
memset(&nfp, 0, nReceiveSize);
if (!Receive((char *) & nfp, nReceiveSize))
{
printf(("Unable to read reply from the SNTP server, get_last_error returns %d\n"), get_last_error());
// Tidy up prior to returning
dwError = get_last_error();
set_last_error(dwError);
return FALSE;
}
//receiving
// Transfer all the useful info into the response structure
response.m_nStratum = nfp.m_Basic.m_Stratum;
response.m_nLeapIndicator = (nfp.m_Basic.m_LiVnMode & 0xC0) >> 6;
response.m_OriginateTime = nfp.m_Basic.m_OriginateTimestamp;
response.m_ReceiveTime = network2host(nfp.m_Basic.m_ReceiveTimestamp);
response.m_TransmitTime = network2host(nfp.m_Basic.m_TransmitTimestamp);
// Tidy up prior to returning
printf("Time was successfully retreived from NTP server\n");
st1 = CNtpTimePacket2Systemtime(response.m_OriginateTime);
st2 = CNtpTimePacket2Systemtime(response.m_ReceiveTime);
st3 = CNtpTimePacket2Systemtime(response.m_TransmitTime);
st4 = CNtpTimePacket2Systemtime(response.m_DestinationTime);
printf("please choose the format of the time,0--64 bits,1--32 bits\n");//32 bit 的数
scanf("%d", &button);
if(button)
{
RoundTripDelay=((response.m_DestinationTime.m_dwInteger) - (response.m_OriginateTime.m_dwInteger))-
((response.m_ReceiveTime.m_dwInteger) - (response.m_TransmitTime.m_dwInteger));
LocalClockOffset =(((response.m_ReceiveTime.m_dwInteger) - (response.m_OriginateTime.m_dwInteger))
+( (response.m_TransmitTime.m_dwInteger) - (response.m_DestinationTime.m_dwInteger))) / 2;
//printf((" DD/MM/YYYY HH:MM:SS.MS\n"));
printf(("Client Originate Date was %u\n"), response.m_OriginateTime.m_dwInteger );
printf(("Server Receive Date was %u\n"), response.m_ReceiveTime.m_dwInteger );
printf(("Server Transmit Date was %u\n"), response.m_TransmitTime.m_dwInteger );
printf(("Client Destination Date was %u\n"), response.m_DestinationTime.m_dwInteger);
printf(("Round trip delay was %u seconds\n"), RoundTripDelay);
printf(("Local clock offset was %u seconds\n"), LocalClockOffset);
}
else
{
response.m_RoundTripDelay =(CNtpTimePacket2Double(response.m_DestinationTime) - CNtpTimePacket2Double(response.m_OriginateTime))-
(CNtpTimePacket2Double(response.m_ReceiveTime) - CNtpTimePacket2Double(response.m_TransmitTime));
response.m_LocalClockOffset =((CNtpTimePacket2Double(response.m_ReceiveTime) - CNtpTimePacket2Double(response.m_OriginateTime))
+(CNtpTimePacket2Double(response.m_TransmitTime) - CNtpTimePacket2Double(response.m_DestinationTime))) / 2;
printf((" DD/MM/YYYY HH:MM:SS.MS\n"));
printf(("Client Originate Date was %02d/%02d/%04d, %02d:%02d:%02d.%03d\n"),
st1.wDay, st1.wMonth, st1.wYear, st1.wHour, st1.wMinute, st1.wSecond, st1.wMilliseconds);
printf(("Server Receive Date was %02d/%02d/%04d, %02d:%02d:%02d.%03d\n"),
st2.wDay, st2.wMonth, st2.wYear, st2.wHour, st2.wMinute, st2.wSecond, st2.wMilliseconds);
printf(("Server Transmit Date was %02d/%02d/%04d, %02d:%02d:%02d.%03d\n"),
st3.wDay, st3.wMonth, st3.wYear, st3.wHour, st3.wMinute, st3.wSecond, st3.wMilliseconds);
printf(("Client Destination Date was %02d/%02d/%04d, %02d:%02d:%02d.%03d\n"),
st4.wDay, st4.wMonth, st4.wYear, st4.wHour, st4.wMinute, st4.wSecond, st4.wMilliseconds);
printf(("Round trip delay was %f seconds\n"),response.m_RoundTripDelay);
printf(("Local clock offset was %f seconds\n"),response.m_LocalClockOffset);
}
if (bSynchroniseClock)
{
if (fabs(response.m_LocalClockOffset) < 3600)
{
CNtpTimePacket newTime();
if (SetClientTime(newTime))
printf("time was successfully synchronised\n");
else
printf("Failed to set the local time\n");
}
else
printf("time difference was greater was 1 hour, not synchronizing clock\n");
}
//else
// printf(("Failed to retreive time from NTP server, get_last_error returned %d\n"), get_last_error());
// Don't forget to release out use of the winsock stack
// return ERROR_NONE;
}
Close();
return ERROR_NONE;
}
CNtpTimePacket newTime()
{ NtpServerResponse response;
CNtpTimePacket t=myGetCurrentTime();
CNtpTimePacket time=Double2CNtpTimePacket( CNtpTimePacket2Double(t) + response.m_LocalClockOffset);
return time;
}
/* void get_local_time()
{ ...
}
void set_local_time()
{
#ifdef _WIN32 SetSystemTime();
#else
dsp_set_time();
#endif
}*/
int main(int argc, char *argv[])
{
int i;
int rc;
u16_t wVersionRequested;
u8_t wsMajorVersion=1;
u8_t wsMinorVersion=1;// Initialise the winsock stack
WSADATA wsaData;
NtpServerResponse response;
wVersionRequested = ((u16_t)(((u8_t)(wsMinorVersion)) | ((u16_t)((u8_t)(wsMajorVersion))) << 8));
bSynchroniseClock = FALSE;
if (argc < 2)
{
printf("testsntp host [/s]\n");
printf("where host is the NTP server address and\n");
printf("/s means synchronize the time instead of just displaying the retrieved values\n");
return 1;
}
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
printf("Failed to load winsock stack\n");
return 1;
}
if ((u8_t)(wsaData.wVersion) != wsMajorVersion || (u8_t)(((u16_t)(wsaData.wVersion) != wsMinorVersion) >> 8) & 0xFF)
{
printf ("Winsock stack does not support version which this program requires\n");
return 1;
}
for (i = 0; i < argc && !bSynchroniseClock; i++)
bSynchroniseClock = ((strcmp(argv[i], ("/s"))) == 0);
//while(1)
{
rc = sntp_client("202.115.27.157");
if (rc == ERROR_NOT_FIND_SERVER)
{
printf("not find sntp server");
}
Sleep(1000);
}
// deinit sockt lib
WSACleanup();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -