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类及常用函数功能详解