qt_demoe/ntpclient/ntpclient.cpp

120 lines
2.8 KiB
C++

#include "ntpclient.h"
#include "qmutex.h"
#include "qudpsocket.h"
#include "qdebug.h"
QScopedPointer<NtpClient> NtpClient::self;
NtpClient *NtpClient::Instance()
{
if (self.isNull()) {
static QMutex mutex;
QMutexLocker locker(&mutex);
if (self.isNull()) {
self.reset(new NtpClient);
}
}
return self.data();
}
NtpClient::NtpClient(QObject *parent) : QObject(parent)
{
ntpIP = "ntp1.aliyun.com";
udpSocket = new QUdpSocket(this);
connect(udpSocket, SIGNAL(connected()), this, SLOT(sendData()));
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readData()));
}
void NtpClient::sendData()
{
qint8 LI = 0;
qint8 VN = 3;
qint8 MODE = 3;
qint8 STRATUM = 0;
qint8 POLL = 4;
qint8 PREC = -6;
QDateTime epoch(QDate(1900, 1, 1), QTime(0, 0, 0));
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;
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->write(timeRequest);
}
void NtpClient::setTime_t(uint secsSince1Jan1970UTC)
{
}
void NtpClient::readData()
{
QByteArray newTime;
QDateTime epoch(QDate(1900, 1, 1), QTime(0, 0, 0));
QDateTime unixStart(QDate(1970, 1, 1), QTime(0, 0, 0));
while (udpSocket->hasPendingDatagrams()) {
newTime.resize(udpSocket->pendingDatagramSize());
udpSocket->read(newTime.data(), newTime.size());
};
QByteArray transmitTimeStamp ;
transmitTimeStamp = newTime.right(8);
quint32 seconds = transmitTimeStamp.at(0);
quint8 temp = 0;
for (int i = 1; i <= 3; i++) {
seconds = (seconds << 8);
temp = transmitTimeStamp.at(i);
seconds = seconds + temp;
}
QDateTime dateTime;
uint secs = seconds - epoch.secsTo(unixStart);
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
dateTime.setSecsSinceEpoch(secs);
#else
dateTime.setTime_t(secs);
#endif
#ifdef __arm__
#ifdef arma9
dateTime = dateTime.addSecs(8 * 60 * 60);
#endif
#endif
udpSocket->disconnectFromHost();
//有些时候返回的数据可能有误或者解析不正确,导致填充的时间不正确
if (dateTime.isValid()) {
emit receiveTime(dateTime);
}
}
void NtpClient::setNtpIP(const QString &ntpIP)
{
if (this->ntpIP != ntpIP) {
this->ntpIP = ntpIP;
}
}
void NtpClient::getDateTime()
{
udpSocket->abort();
udpSocket->connectToHost(ntpIP, 123);
}