NTP测试

向NTP服务器发送特定报文,即可收到回复,不考虑传输延迟的话,解析时间很简单。

测试可用的NTP服务器:202.120.2.101 端口:123

例如发送的报文:(48字节)1b 00 04 fa 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

收到的回复是:(48字节)

1C 03 04 E9 00 00 0A 07 00 00 0E 04 CA 76 01 82 D9 FD 82 DE 62 51 F1 C6 00 00 00 00 00 00 00 00 D9 FD 84 95 94 F8 59 7C D9 FD 84 95 94 FB 59 E1   

 

然后就可以根据协议解析时间了。

 

 

上图用网络调试助手发送和接收

 

 

参考代码:

#include <stdio.h>   
#include "winsock2.h"   
#include <time.h>   
  
#include <conio.h>   
  
#pragma  comment (lib,"ws2_32.lib")//连入库文件   
//******************************//   
// 定义一个结构,就是NTP包的结构//   
//******************************//   
/*NTP 消息的格式被显示如下。  
                    1                   2                   3 
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |LI | VN  |Mode |    Stratum    |     Poll      |   Precision   | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                            根延迟                             | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                            根差量                             | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                          参考标识符                           | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                                                               | 
      |                          参考时间戳(64)                       | 
      |                                                               | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                                                               | 
      |                           原始时间戳(64)                      | 
      |                                                               | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                                                               | 
      |                           接受时间戳 (64)                     | 
      |                                                               | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                                                               | 
      |                          传送时间戳(64)                       | 
      |                                                               | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
      |                                                               | 
      |                                                               | 
      |                         认证符(可选项) (96)                   | 
      |                                                               | 
      |                                                               | 
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 
 
  */  
typedef struct ntp {  
char Flag;  
char PeerClockStratum;  
char PeerPollingInterval;  
char PeerClockPrecision;  
char RootDelay[4];  
char ClockDispersion[4];  
char ReferenceClock[4];  
char ReferenceClockUpdateTime[8];  
char OriginateTimeStamp[8];  
char ReceiveTimeStamp[8];  
char TransmitTimeStamp[8];  
} tagNTP;  
  
//*********************************************************//   
// 定义一个函数,设置操作系统时间的函数 //   
// SetNewTime - sets system time //   
// Return value - TRUE if successful, FALSE otherwise //   
// hour - new hour (0-23) //   
// minutes - new minutes (0-59) //   
// Author:白色猎人 [Unicorn QQ:233536605] //   
//*********************************************************//   
BOOL SetNewTime(WORD year,WORD month,WORD day,WORD hour, WORD minutes,WORD second)   
{  
    SYSTEMTIME st;  
    GetSystemTime(&st); // gets current time   
    st.wYear=year+1900; // adjusts year   
    st.wMonth=month+1; // adjusts month   
    st.wDay =day; // adjusts day   
    st.wHour =hour; // adjusts hours    
    st.wMinute =minutes; // and minutes   
    st.wSecond =second; // and second   
    if (!SetLocalTime(&st))   
        return FALSE;// sets system time   
    return TRUE;  
}  
  
typedef unsigned char uchar;  
  
  
void printn(uchar *buf,uchar len)  
{  
    while(len--)  
    {  
        printf("0x%02x ",*buf++);  
    }  
}  
  
void main()   
{  
    SYSTEMTIME st;  
    WSADATA wsaData;  
    SOCKET SendSocket;  
    sockaddr_in RecvAddr;  
    //Receive Data   
    sockaddr_in SenderAddr;  
    int SenderAddrSize = sizeof(SenderAddr);  
    ntp SendBuf;   
    int Port = 123; //NTP端口为:123   
    //以下变量的赋值均来源于NTP数据包,你可以用Ethereal抓包   
    SendBuf.Flag =0x1b;//0001 1011   
    SendBuf.PeerClockStratum =0x00;  
    SendBuf.PeerPollingInterval =0x00;  
    SendBuf.PeerClockPrecision =0x00;  
    memset(SendBuf.RootDelay ,0,4);  
    memset(SendBuf.ClockDispersion,0,4);  
    memset(SendBuf.ReferenceClock,0,4);  
    memset(SendBuf.ReferenceClockUpdateTime,0,8);  
    memset(SendBuf.OriginateTimeStamp,0,8);  
    memset(SendBuf.ReceiveTimeStamp,0,8);  
    //memcpy(&SendBuf.TransmitTimeStamp[0],"0xc7",1);   
    //memcpy(&SendBuf.TransmitTimeStamp[1],"0x50",1);   
    //memcpy(&SendBuf.TransmitTimeStamp[2],"0xe7",1);   
    //memcpy(&SendBuf.TransmitTimeStamp[3],"0xa0",1);   
    //SendBuf.TransmitTimeStamp[0]=0xc7;   
    //SendBuf.TransmitTimeStamp[1]=0x50;   
    //SendBuf.TransmitTimeStamp[2]=0xe7;   
    //SendBuf.TransmitTimeStamp[3]=0xa0;   
    SendBuf.TransmitTimeStamp[0]=0;  
    SendBuf.TransmitTimeStamp[1]=0;  
    SendBuf.TransmitTimeStamp[2]=0;  
    SendBuf.TransmitTimeStamp[3]=0;  
    SendBuf.TransmitTimeStamp[4]=0x00;  
    SendBuf.TransmitTimeStamp[5]=0x00;  
    SendBuf.TransmitTimeStamp[6]=0x00;  
    SendBuf.TransmitTimeStamp[7]=0x00;  
  
    char *ptr;  
    ptr=(char *)&SendBuf;  
    int i;  
    for(i=0;i<sizeof(SendBuf);i++)  
    {  
        printf("%x\r\n",*(ptr+i));  
    }  
      
  *(ptr+0)= (0 <<6) | (3 <<3) | (3);  
     *(ptr+1)= 0;  
        *(ptr+2)= 4;  
 *(ptr+3)= -6 & 0xff;  
         *(ptr+5)= 1;  
         *(ptr+9)= 1;  
  
  
  
    int BufLen = 48; //包的长度为48字节   
  
    tm *newtime;   
    time_t long_time;  
    //---------------------------------------------   
    // Initialize Winsock   
    WSAStartup(MAKEWORD(2,2), &wsaData);  
  
    //---------------------------------------------   
    // Create a socket for sending data   
    SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  
  
    // Set up the RecvAddr structure with the IP address of the receiver (in this example case "123.456.789.1") and the specified port number.   
    RecvAddr.sin_family = AF_INET;  
    RecvAddr.sin_port = htons(Port);  
    //RecvAddr.sin_addr.s_addr = inet_addr("61.129.42.44");   
    //RecvAddr.sin_addr.s_addr = inet_addr("time.windows.com");   
    //RecvAddr.sin_addr.s_addr = inet_addr("192.168.2.101");   
    RecvAddr.sin_addr.s_addr = inet_addr("202.120.2.101");  
      
    //RecvAddr.sin_addr.s_addr = inet_addr("cn.pool.ntp.org");   
    //RecvAddr.sin_addr.s_addr = inet_addr("133.100.11.8");//"133.100.11.8");//"133.100.9.2"); 两个一级代理好用   
    //所有的服务器见http://support.microsoft.com/?scid=kb;zh-cn;262680&spid=1131&sid=795//地址为210.72.145.44 (中国国家授时中心)   
  
    // Send a datagram to the receiver   
    printf("Sending a datagram to the receiver...\n");  
    sendto(SendSocket, (char *)&SendBuf, BufLen, 0, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr));  
  
    printf("%d\r\n",sizeof(RecvAddr));  
    printn((uchar*)&SendBuf,48);  
  
    //printf("Finished sending.\n");   
  
    /*开始接收发过来的数据*/  
    printf("Receiving datagrams...\n");  
    recvfrom(SendSocket,(char *)&SendBuf, BufLen, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);  
    //printf("Finished receiving.Closing socket.\n");   
    closesocket(SendSocket);  
    //*********************************************   
    memcpy(&long_time,SendBuf.ReceiveTimeStamp,4); //从收到的包里面取出前32位放入变量long_time中   
  
    printn((uchar*)&SendBuf,48);  
  
    //printf("%d\n",long_time);   
    long_time = ntohl(long_time)-2208988800; //把低位的字节和高位字节互换   
    newtime = localtime(&long_time); /* Convert to local time. */  
    SetNewTime(newtime->tm_year,newtime->tm_mon,newtime->tm_mday,newtime->tm_hour,newtime->tm_min,newtime->tm_sec);  
    GetSystemTime(&st); // gets current time   
    st.wYear=newtime->tm_year+1900; // adjusts year   
    st.wMonth=newtime->tm_mon+1; // adjusts month   
    st.wDay =newtime->tm_mday; // adjusts day   
    st.wHour =newtime->tm_hour; // adjusts hours    
    st.wMinute =newtime->tm_min; // and minutes   
    st.wSecond =newtime->tm_sec; // and second   
      
      
    SetLocalTime(&st);// sets system time   
    //---------------------------------------------   
    // Clean up and quit.   
    //---------------------------------------------   
    //printf("OK,Exiting.\n");   
  
    printf("%d年%d月%d日%d时%d分%d秒",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);  
    WSACleanup();  
    getch();  
    return;  
}  
  
/* 
0x1b 0x00 0x04 0xfa 0x00 0x01 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
 
 
1b 00 04 fa 00 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
 
*/  

  

 

posted on 2015-11-26 18:43  鲜于超  阅读(960)  评论(0编辑  收藏  举报

导航