Qt自动同步时间

Qt自动同步时间

Qt自动同步时间需要使用网络时间协议(Network Time Protoco, NTP)。

首先需要include一个UDP库

#include <QUdpSocket>

然后在头文件声明

signals:
    void connected();
    void readyRead();

public slots:
    void setNtp();
    void connectsucess();
    void readingDataGrams();

接着在.cpp中实现

void TimeSetting::setNtp()
{
    ntpIP = "time.windows.com";    //windows NTP服务器地址

    udpSocket = new QUdpSocket(this);
    connect(udpSocket,SIGNAL(connected()),this,SLOT(connectsucess()));
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readingDataGrams()));
    udpSocket->connectToHost(ntpIP,123);
}

void TimeSetting::connectsucess()
{
    qint8 LI=0;  //无预告
    qint8 VN=3;  //版本号
    qint8 MODE=3; //客户端几
    qint8 STRATUM=0;//表示本地时钟层次水平
    qint8 POLL=4; //测试间隔
    qint8 PREC=-6; //表示本地时钟精度
    QDateTime Epoch(QDate(1900, 1, 1));
    qint32 second=quint32(Epoch.secsTo(QDateTime::currentDateTime()));

    qint32 temp=0;
    QByteArray timeRequest(48, 0);
    timeRequest[0]=(LI <<6) | (VN <<3) | (MODE);
    timeRequest[1]=STRATUM;
    timeRequest[2]=POLL;
    timeRequest[3]=PREC & 0xff;
    timeRequest[5]=1;
    timeRequest[9]=1;

    //40到43字节保存原始时间戳,即客户端发送的时间
    timeRequest[40]=(temp=(second&0xff000000)>>24);
    temp=0;
    timeRequest[41]=(temp=(second&0x00ff0000)>>16);
    temp=0;
    timeRequest[42]=(temp=(second&0x0000ff00)>>8);
    temp=0;
    timeRequest[43]=((second&0x000000ff));
    udpSocket -> flush();
    udpSocket -> write(timeRequest);
    udpSocket -> flush();
}

void TimeSetting::readingDataGrams()
{
    QByteArray newTime;
    QDateTime Epoch(QDate(1900, 1, 1));
    QDateTime unixStart(QDate(1970, 1, 1));
    do
    {
        newTime.resize(udpSocket->pendingDatagramSize());
        udpSocket->read(newTime.data(), newTime.size());
    }while(udpSocket->hasPendingDatagrams());

    QByteArray TransmitTimeStamp ;
    TransmitTimeStamp=newTime.right(8);
    quint32 seconds=TransmitTimeStamp[0];
    quint8 temp=0;
    for(int j=1;j<=3;j++)
    {
        seconds=seconds<<8;
        temp=TransmitTimeStamp[j];
        seconds=seconds+temp;
    }
    QDateTime time;
    time.setTime_t(seconds-Epoch.secsTo(unixStart));

    this->udpSocket->disconnectFromHost();
    this->udpSocket->close();
}

接下来大概分析一下上述代码。

ntpIP = "time.windows.com";这句指定一个NTP服务器,NTP协议基于UDP,用于网络时间同步的协议,使网络中的计算机时钟同步到UTC,再配合各个时区的偏移调整就能实现精准同步对时功能。提供NTP对时的服务器有很多,比如微软的NTP对时服务器,利用NTP服务器提供的对时功能,可以使我们的设备时钟系统能够正确运行。123端口是系统的时间服务,udpSocket->connectToHost(ntpIP,123);将套接字连接到服务器。

为保证传输速度,NTP服务默认使用UDP协议,因此存在有丢包的可能。可根据实际使用地点选择NTP服务器,保证使用的可靠性。

两个槽函数connectsucess()readingDataGrams()分别负责向NTP服务器发送报文和接收报文。

发送报文的具体形式及其含义在connectsucess()中的注释解释了,接着通过udpSocket -> write(timeRequest);发送到NTP服务器。

接收到的报文通过一定的字符解析方法,通过判断出传送时延,解析到正确的网络时间。上述代码中的QDateTime time就是最终解析到的网络时间,它的形式如下:

Sat Feb 6 11:11:11 2021

最后解析上述字符串就可以得到所需的信息。

解析字符串方法可参考:Qt QString类及常用函数功能详解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值