Linux之通过NTP协议实现服务器时间同步的源码

Linux下通过NTP协议实现服务器时间同步(C实现)

  (2009-12-09 20:59:41)
转载
标签: 

ntp

 

linux

 

时间同步

 

杂谈

 
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define  int8      char
#define  uint8     unsigned char
#define  uint32    unsigned int
#define  ulong32   unsigned long
#define  long32    long
#define  int32     int
#define  long64    long long

#define  debug

//3600s*24h*(365days*70years+17days)
#define  From00to70 0x83aa7e80U

#define  NTPSVR1  "132.163.4.102"        //USA
#define  NTPSVR2  "132.163.135.132"      //USA
#define  NTPSVR3  "192.53.103.103"       //Germany

#define  NTPPORT  123
typedef struct NTPPACKET
{
  uint8     li_vn_mode;
  uint8     stratum;
  uint8     poll;
  uint8     precision;
  ulong32   root_delay;
  ulong32   root_dispersion;
  int8      ref_id[4];
  ulong32   reftimestamphigh;
  ulong32   reftimestamplow;
  ulong32   oritimestamphigh;
  ulong32   oritimestamplow;
  ulong32   recvtimestamphigh;
  ulong32   recvtimestamplow;
  ulong32   trantimestamphigh;  
  ulong32   trantimestamplow;
}NTPPacket;

NTPPacket  ntppack,newpack;

//定义为long64,解决32位数的符号位问题
long64   firsttimestamp,finaltimestamp;
long64   diftime,delaytime;

void NTP_Init()
{
  bzero(&ntppack,sizeof(ntppack));
  ntppack.li_vn_mode=0x1b;//0|(3<<2)|(3<<5);
  //获取初始时间戳T1
  firsttimestamp="From00to70"+time(NULL);//-8*3600;
  ntppack.oritimestamphigh=htonl(firsttimestamp);
}
int main()
{

//  ulong32 clienttime;
//  ulong32 diftime,firsttimestamp,finaltimestamp;
  fd_set  inset1;
  int32  sockfd;
  struct tim tv,tv1;
  struct timezone tz;
  struct sockaddr_in addr;
// printf("%d,%d,%d\n",&ntppack.li_vn_mode,&ntppack.stratum,&ntppack.poll);
// printf("%d  %ld\n",sizeof(NTPPacket),sizeof(ntppack));
 
//  printf("%ld\n",time(NULL));
 
  if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
    {
      perror("create socket error!\n");
      exit(1);
    }
 
  addr.sin_family=AF_INET;   //IPV4协议
  addr.sin_port =htons(NTPPORT);   //NTP专用的123端口
  addr.sin_addr.s_addr=inet_addr(NTPSVR1);   //校时服务器
  bzero(&(addr.sin_zero),8);   //清零
 
  //wait 5s
  tv.tv_sec=10;    //select等待时间为10S
  tv.tv_usec=0;
 
  FD_ZERO(&inset1);
  FD_SET(sockfd,&inset1);
 
  NTP_Init();
  //发送数据请求包
  sendto(sockfd,&ntppack,sizeof(ntppack),0,(struct sockaddr *)&addr,sizeof(struct sockaddr));
  //select巡视
  if(select(sockfd+1,&inset1,NULL,NULL,&tv)<0)
  {
    perror("select error!\n");
    exit(1);
  }
  else
  {
  //printf("OK\n");
    if(FD_ISSET(sockfd,&inset1))
    {
  // printf("OK\n");
     if(recv(sockfd,&newpack,sizeof(newpack),0)<0)        //接收数据在newpack中。
     {
      perror("recv error!\n");
      exit(1);
     }
    }
  }
  //到达客户机时间戳T4
  finaltimestamp=time(NULL)+From00to70;//-8*3600;
 
  //将网络上传送的大端数据改为小端形式。
 newpack.root_delay= ntohl(newpack.root_delay);
 newpack.root_dispersion= ntohl(newpack.root_dispersion);
 newpack.reftimestamphigh=ntohl(newpack.reftimestamphigh);
 newpack.reftimestamplow= ntohl(newpack.reftimestamplow);
 newpack.oritimestamphigh= ntohl(newpack.oritimestamphigh);
 newpack.oritimestamplow= ntohl(newpack.oritimestamplow);
 newpack.recvtimestamphigh= ntohl(newpack.recvtimestamphigh);
 newpack.recvtimestamplow= ntohl(newpack.recvtimestamplow);
 newpack.trantimestamphigh= ntohl(newpack.trantimestamphigh);
 newpack.trantimestamplow= ntohl(newpack.trantimestamplow);
 
 //求出客户机跟服务器的时间差=((T2-T1)+(T3-T4))/2

你可能感兴趣的:(Linux)