在ubuntu上使用C++获取ntp时间

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

在项目中需要同步时间,采用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;
}

以上就是在ubuntu系统中使用C++从阿里云NTP服务器获取时间。需要注意,在将NTP时间戳值转换为Linux时间戳值时,需要将NTP时间戳值减去NTP起始时间戳值(1900-01-01 00:00:00)和Linux起始时间戳值(1970-01-01 00:00:00)之间的差值(2208988800)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值