提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
在项目中需要同步时间,采用GPS与网络时间两种方式实现。网络时间则从NTP服务器获取。
一、在linux中使用UDP协议获取时间
应为ntp协议是udo协议中的一种,所以通过UDP socket将请求发送到服务器。然后,我们等待NTP服务器的响应,并解析响应数据包以获取时间戳,从而计算出对应的Linux时间。
二、代码实现
1.完整代码如下
代码如下(示例):
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
using namespace std;
int main(int argc, char **argv)
{
const char *ntp_server = "ntp.aliyun.com";
// 创建一个UDP socket
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd == -1)
{
perror("socket error");
exit(EXIT_FAILURE);
}
// 设置超时时间为5秒钟
struct timeval timeout = {5, 0};
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
// 解析NTP服务器的IP地址
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
struct addrinfo *results;
int status = getaddrinfo(ntp_server, "123", &hints, &results);
if (status != 0)
{
cerr << "getaddrinfo error: " << gai_strerror(status) << endl;
exit(EXIT_FAILURE);
}
struct sockaddr_in ntp_addr;
memcpy(&ntp_addr, results->ai_addr, sizeof(struct sockaddr_in));
freeaddrinfo(results);
ntp_addr.sin_port = htons(123); // NTP协议使用的是端口号123
// 构造NTP请求数据包
char ntp_pkt[48];
memset(ntp_pkt, 0, sizeof(ntp_pkt));
ntp_pkt[0] = 0x1b;
// 发送NTP请求数据包并等待响应
if (sendto(sockfd, ntp_pkt, sizeof(ntp_pkt), 0, (struct sockaddr *)&ntp_addr, sizeof(ntp_addr)) == -1)
{
perror("sendto error");
exit(EXIT_FAILURE);
}
// 接收NTP响应数据包
int nbytes;
char buf[1024];
struct sockaddr_in srv_addr;
socklen_t srv_addr_len = sizeof(srv_addr);
while ((nbytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&srv_addr, &srv_addr_len)) == -1)
;
// 解析NTP响应数据包
if (nbytes == sizeof(ntp_pkt))
{
unsigned long long *timestamp = (unsigned long long *)&buf[40];
time_t linux_time = ntohl(*timestamp) - 2208988800UL;
cout << "NTP time: " << ctime(&linux_time);
}
else
{
cerr << "Received invalid NTP packet." << endl;
}
// 关闭socket
close(sockfd);
return 0;
}