⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sntp.c

📁 基于SNTP协议的时间同步客户端的c代码。其中计算传输时间偏移和同步误差都在客户端实现。可顺利移植到DSP上
💻 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 + -