c/c++代码获取网络时间(从NTP授时服务器获取)

有时候需要获取网络时间,又没有自己的服务器去返回,那么可以考虑从NTP授时服务器获取,windows的同步网络时间就是从NTP授时服务器获取的。

NTP授时服务器协议采用UDP,端口一般为123,下面给出从github上整理的代码,亲测可用,授时服务器地址选用的是阿里云的公共NTP服务器。

INT64 GetNTPTime()
{
    //初始化网络库
    WSADATA wsaData;
	::WSAStartup(MAKEWORD(2, 2), &wsaData);
    //下面是获取过程
	INT64 curTm = 0;
	struct hostent *host = NULL;
	int nErrno = 0;

	const char *server = "ntp.aliyun.com";
	const char *port = "123";
	ADDRINFOA hints, *res, *ap; /* address info structs */
	socklen_t addrlen = sizeof(struct sockaddr_storage);

	struct ntpPacket{
		UINT8 flags;
		UINT8 stratum;
		UINT8 poll;
		UINT8 precision;
		UINT32 root_delay;
		UINT32 root_dispersion;
		UINT8 referenceID[4];
		UINT32 ref_ts_sec;
		UINT32 ref_ts_frac;
		UINT32 origin_ts_sec;
		UINT32 origin_ts_frac;
		UINT32 recv_ts_sec;
		UINT32 recv_ts_frac;
		UINT32 trans_ts_sec;
		UINT32 trans_ts_frac;
	};
#define ENDIAN_SWAP32(data)  	((data >> 24) | /* right shift 3 bytes */ \
	((data & 0x00ff0000) >> 8) | /* right shift 1 byte */ \
	((data & 0x0000ff00) << 8) | /* left shift 1 byte */ \
	((data & 0x000000ff) << 24)) /* left shift 3 bytes */

	struct ntpPacket packet;
	UINT8 *ptr = (UINT8 *)(&packet); /* to read raw bytes */

	int server_sock; /* send through this socket */
	int error; /* error checking */
	unsigned int recv_secs;

	/* server is required, port is optional */
	memset(&packet, 0, sizeof(struct ntpPacket));
	packet.flags = 0xe3;

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_DGRAM;

	/* fill our address structs for ntp server */
	error = getaddrinfo(server, port, &hints, &res);
	/* loop through results */
	for (ap = res; ap != NULL; ap = ap->ai_next) {
		server_sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
		if (server_sock == -1)
			continue;
		break;
	}
	if (ap == NULL) {
		return curTm;
	}

	error = ::sendto(server_sock, (const char*)&packet, sizeof(struct ntpPacket), 0, ap->ai_addr, addrlen);
	if (error == -1) {
		return curTm;
	}
	error = recvfrom(server_sock, (char*)&packet, sizeof(struct ntpPacket), 0, ap->ai_addr, &addrlen);
	if (error == -1) {
		return curTm;
	}

	freeaddrinfo(res); /* all done */

	/* correct for right endianess */
	packet.recv_ts_sec = ENDIAN_SWAP32(packet.recv_ts_sec);

	/* print date with receive timestamp */
	recv_secs = packet.recv_ts_sec - 2208988800L; /* convert to unix time */
	curTm = recv_secs;
	
	return curTm;
}

代码比较粗糙,比如没有加winsock2.h等头文件,比如没有WSACleanup()等,请使用者根据自己的实际使用情况自行添加和优化

代码我是在win下面跑的,一切正常。linux和unix下,稍微改改也可以跑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值