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

📄 ntp.c

📁 linux下网络通信套接字编程
💻 C
字号:
#include <sys/socket.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
struct NTPPacket
{
char Leap_Ver_Mode;
/*client=0*/
char Startum; 
char Poll;
char Precision;
double RootDelay;
double Dispersion;
char RefIdentifier[4];
char RefTimeStamp[8];
char OriTimeStamp[8];
char RecvTimeStamp[8];
char TransTimeStamp[8];
};

#define NTPPORT         123
#define TIMEPORT        37
#define NTPV1   "NTP/V1"
#define NTPV2   "NTP/V2"
#define NTPV3   "NTP/V3"
#define NTPV4   "NTP/V4"
#define TIME    "TIME/UDP"
double SecondBef1970;
struct sockaddr_in sin;
struct addrinfo         hints, *res=NULL;
int rc,sk;
char Protocol[32];
/*构建NTP协议包*/
int ConstructPacket(char *Packet)
{
char Version=1;
long SecondFrom1900;
long Zero=0;
int Port;
time_t timer;
strcpy(Protocol,NTPV1);
/*判断协议版本*/
if(strcmp(Protocol,NTPV1)||strcmp(Protocol,NTPV2)||strcmp(Protocol,NTPV3)||strcmp(Protocol,NTPV4))
{
	Port=NTPPORT;
	Version=Protocol[6]-0x30;
	Packet[0]=(Version<<3)|3;       //LI--Version--Mode
	Packet[1]=0;            //Startum
	Packet[2]=0;            //Poll interval
	Packet[3]=0;            //Precision
/*包括Root delay、Root disperse和Ref Indentifier */
	memset(&Packet[4],0,12);
/*包括Ref timestamp、Ori timastamp和Receive Timestamp */
	memset(&Packet[16],0,24);
	time(&timer);
	SecondFrom1900=SecondBef1970+(long)timer;
	SecondFrom1900=htonl(SecondFrom1900);
	memcpy(&Packet[40],&SecondFrom1900,4);
	memcpy(&Packet[44],&Zero,4);
	return 48;
	}
else    //time/udp
{
	Port=TIMEPORT;
	memset(Packet,0,4);
	return 4;
	}
return 0;
}

/*计算从1900年到现在一共有多少秒*/
long GetSecondFrom1900(int End)
{
int Ordinal=0;
int Run=0;
long Result;
int i;
	for(i=1900;i<End;i++)
	{
		if(((i%4==0)&&(i%100!=0))||(i%400==0)) Run++;
		else Ordinal++;
	}
	Result=(Run*366+Ordinal*365)*24*3600;
	return Result;
}

/*获取NTP时间*/
long GetNtpTime(int sk,struct addrinfo *res)
{
char Content[256];
int  PacketLen;
fd_set PendingData;
struct timeval BlockTime;
int  FromLen;
int  Count=0;
int  result,i;
int  re;
struct NTPPacket RetTime;
	PacketLen=ConstructPacket(Content);
	if(!PacketLen)
		 return 0;
/*客户端给服务器端发送NTP协议数据包*/
	if((result=sendto(sk,Content,PacketLen,0,res->ai_addr,res->ai_addrlen))<0)
		perror("sendto");
	else
		printf("sendto success result=%d \n",result);
	for(i=0;i<5;i++)
	{
		printf("in for\n");
/*调用select函数,并设定超时时间为1秒*/
		FD_ZERO(&PendingData);
		FD_SET(sk, &PendingData);
		BlockTime.tv_sec=1;
		BlockTime.tv_usec=0;
		if(select(sk+1,&PendingData,NULL,NULL,&BlockTime)>0)
		{
			FromLen=sizeof(sin);
/*接收服务器端的信息*/
			if((Count=recvfrom(sk,Content,256,0,res->ai_addr,&(res->ai_addrlen)))<0)
				perror("recvfrom");
			else
				printf("recvfrom success,Count=%d \n",Count);
			if(Protocol==TIME)
			{
				memcpy(RetTime.TransTimeStamp,Content,4);
				return 1;
			}
			else if(Count>=48&&Protocol!=TIME)
			{
				RetTime.Leap_Ver_Mode=Content[0];
				RetTime.Startum=Content[1];
				RetTime.Poll=Content[2];
				RetTime.Precision=Content[3];
				memcpy((void *)&RetTime.RootDelay,&Content[4],4);
				memcpy((void *)&RetTime.Dispersion,&Content[8],4);
				memcpy((void *)RetTime.RefIdentifier,&Content[12],4);
				memcpy((void *)RetTime.RefTimeStamp,&Content[16],8);
				memcpy((void *)RetTime.OriTimeStamp,&Content[24],8);
				memcpy((void *)RetTime.RecvTimeStamp,&Content[32],8);
				memcpy((void *)RetTime.TransTimeStamp,&Content[40],8);
				return 1;
			}
		}
	}
	close(sk);
	return 0;
}

int main()
{
	memset(&hints,0,sizeof(hints));
	hints.ai_family=PF_UNSPEC;
	hints.ai_socktype=SOCK_DGRAM;
	hints.ai_protocol=IPPROTO_UDP;
/*调用getaddrinfo函数,获取地址信息*/
	rc=getaddrinfo("200.205.253.254","123",&hints,&res);
	if (rc != 0) {
		perror("getaddrinfo");
		return;
	}
	sk = socket(res->ai_family, res->ai_socktype,res->ai_protocol);
	if (sk <0 ) {
		perror("socket");
	}
	else
	{
		printf("socket success!\n");
	}
/*调用取得NTP时间函数*/
	GetNtpTime(sk,res);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -