Hi I am trying to make NTP client which sync system time from NtpServer, and is Platform Independent for LINUX and WIN.
-
Hi I am trying to make a ntp client which sync system time of Linux and windows:
Here is my progress:#include "ntpclient.h" #include <QHostInfo> #include <QNetworkDatagram> #include <QDataStream> #ifdef Q_OS_WIN #include <Windows.h> #endif NtpClient::NtpClient(QObject *parent) : QObject(parent) { m_udpSocket = new QUdpSocket(this); m_udpSocket->connectToHost("server 0.in.pool.ntp.org", 123); connect(m_udpSocket, &QUdpSocket::readyRead, this, &NtpClient::readPendingDatagrams); } QDateTime NtpClient::getDateTime() { return m_time; } void NtpClient::readPendingDatagrams() { while (m_udpSocket->hasPendingDatagrams()) { QNetworkDatagram datagram = m_udpSocket->receiveDatagram(); QByteArray buffer = datagram.data(); QDataStream stream(&buffer, QIODevice::ReadOnly); // Check the NTP version and mode quint8 flags; stream >> flags; quint8 version = (flags & 0x38) >> 3; quint8 mode = flags & 0x07; if (version != 4 || mode != 4) { continue; } // Extract the transmit timestamp from the NTP packet quint32 seconds, fraction; stream >> seconds >> fraction; QDateTime transmitTime = QDateTime::fromMSecsSinceEpoch((quint64)seconds * 1000 - 2208988800000 + (quint64)fraction * 1000 / 0x100000000); // Set the system time to the NTP time m_time = transmitTime; #ifdef Q_OS_WIN setSystemTimeWindows(transmitTime); #elif defined(Q_OS_LINUX) setSystemTimeLinux(transmitTime); #endif emit dateTimeReceived(); } } #ifdef Q_OS_LINUX void NtpClient::setSystemTimeLinux(const QDateTime& dateTime) { QString dateTimeStr = dateTime.toString(Qt::ISODate); qDebug() << "Setting system time to" << dateTimeStr; // Set the system date and time using the "date" command QStringList arguments; arguments << "-s" << dateTimeStr; QProcess::execute("date", arguments); // Check that the system time was set correctly QDateTime systemTime = QDateTime::currentDateTime(); qint64 diffSeconds = dateTime.secsTo(systemTime); if (qAbs(diffSeconds) > 1) { qWarning() << "Failed to set system time to" << dateTimeStr; emit systemTimeSet(false); } else { qDebug() << "System time is now" << systemTime.toString(Qt::ISODate); emit systemTimeSet(true); } } #endif #ifdef Q_OS_WIN void NtpClient::setSystemTimeWindows(const QDateTime& dateTime) { SYSTEMTIME st; st.wYear = dateTime.date().year(); st.wMonth = dateTime.date().month(); st.wDay = dateTime.date().day(); st.wHour = dateTime.time().hour(); st.wMinute = dateTime.time().minute(); st.wSecond = dateTime.time().second(); st.wMilliseconds = dateTime.time().msec(); qDebug() << "Setting system time to" << dateTime.toString(Qt::ISODate); if (!SetSystemTime(&st)) { qWarning() << "Failed to set system time:" << GetLastError(); emit systemTimeSet(false); } else { QDateTime systemTime = QDateTime::fromSecsSinceEpoch(time(nullptr)); qDebug() << "System time is now" << systemTime.toString(Qt::ISODate); emit systemTimeSet(true); } } #endif
The code is compilable in both OS, but is not syncing system time.
Any Idea? What I am doing wrong? And is there any other way to do this? -
Hi I am trying to make a ntp client which sync system time of Linux and windows:
Here is my progress:#include "ntpclient.h" #include <QHostInfo> #include <QNetworkDatagram> #include <QDataStream> #ifdef Q_OS_WIN #include <Windows.h> #endif NtpClient::NtpClient(QObject *parent) : QObject(parent) { m_udpSocket = new QUdpSocket(this); m_udpSocket->connectToHost("server 0.in.pool.ntp.org", 123); connect(m_udpSocket, &QUdpSocket::readyRead, this, &NtpClient::readPendingDatagrams); } QDateTime NtpClient::getDateTime() { return m_time; } void NtpClient::readPendingDatagrams() { while (m_udpSocket->hasPendingDatagrams()) { QNetworkDatagram datagram = m_udpSocket->receiveDatagram(); QByteArray buffer = datagram.data(); QDataStream stream(&buffer, QIODevice::ReadOnly); // Check the NTP version and mode quint8 flags; stream >> flags; quint8 version = (flags & 0x38) >> 3; quint8 mode = flags & 0x07; if (version != 4 || mode != 4) { continue; } // Extract the transmit timestamp from the NTP packet quint32 seconds, fraction; stream >> seconds >> fraction; QDateTime transmitTime = QDateTime::fromMSecsSinceEpoch((quint64)seconds * 1000 - 2208988800000 + (quint64)fraction * 1000 / 0x100000000); // Set the system time to the NTP time m_time = transmitTime; #ifdef Q_OS_WIN setSystemTimeWindows(transmitTime); #elif defined(Q_OS_LINUX) setSystemTimeLinux(transmitTime); #endif emit dateTimeReceived(); } } #ifdef Q_OS_LINUX void NtpClient::setSystemTimeLinux(const QDateTime& dateTime) { QString dateTimeStr = dateTime.toString(Qt::ISODate); qDebug() << "Setting system time to" << dateTimeStr; // Set the system date and time using the "date" command QStringList arguments; arguments << "-s" << dateTimeStr; QProcess::execute("date", arguments); // Check that the system time was set correctly QDateTime systemTime = QDateTime::currentDateTime(); qint64 diffSeconds = dateTime.secsTo(systemTime); if (qAbs(diffSeconds) > 1) { qWarning() << "Failed to set system time to" << dateTimeStr; emit systemTimeSet(false); } else { qDebug() << "System time is now" << systemTime.toString(Qt::ISODate); emit systemTimeSet(true); } } #endif #ifdef Q_OS_WIN void NtpClient::setSystemTimeWindows(const QDateTime& dateTime) { SYSTEMTIME st; st.wYear = dateTime.date().year(); st.wMonth = dateTime.date().month(); st.wDay = dateTime.date().day(); st.wHour = dateTime.time().hour(); st.wMinute = dateTime.time().minute(); st.wSecond = dateTime.time().second(); st.wMilliseconds = dateTime.time().msec(); qDebug() << "Setting system time to" << dateTime.toString(Qt::ISODate); if (!SetSystemTime(&st)) { qWarning() << "Failed to set system time:" << GetLastError(); emit systemTimeSet(false); } else { QDateTime systemTime = QDateTime::fromSecsSinceEpoch(time(nullptr)); qDebug() << "System time is now" << systemTime.toString(Qt::ISODate); emit systemTimeSet(true); } } #endif
The code is compilable in both OS, but is not syncing system time.
Any Idea? What I am doing wrong? And is there any other way to do this? -
When you say " but is not syncing system time." surely the first thing is to separate out the reading of the time from the net versus the setting of that time via the OS call. How should anyone but you know which area it is failing in?
For the Linux btw: who are you running as? Also you issue a
date -s
OS command while under Windows you make a system call. See maybe https://stackoverflow.com/questions/28314543/set-system-date-and-time-using-c-in-linux for Linux system calls, as well as caveats about doing this thing. -
Hi I am trying to make a ntp client which sync system time of Linux and windows:
Here is my progress:#include "ntpclient.h" #include <QHostInfo> #include <QNetworkDatagram> #include <QDataStream> #ifdef Q_OS_WIN #include <Windows.h> #endif NtpClient::NtpClient(QObject *parent) : QObject(parent) { m_udpSocket = new QUdpSocket(this); m_udpSocket->connectToHost("server 0.in.pool.ntp.org", 123); connect(m_udpSocket, &QUdpSocket::readyRead, this, &NtpClient::readPendingDatagrams); } QDateTime NtpClient::getDateTime() { return m_time; } void NtpClient::readPendingDatagrams() { while (m_udpSocket->hasPendingDatagrams()) { QNetworkDatagram datagram = m_udpSocket->receiveDatagram(); QByteArray buffer = datagram.data(); QDataStream stream(&buffer, QIODevice::ReadOnly); // Check the NTP version and mode quint8 flags; stream >> flags; quint8 version = (flags & 0x38) >> 3; quint8 mode = flags & 0x07; if (version != 4 || mode != 4) { continue; } // Extract the transmit timestamp from the NTP packet quint32 seconds, fraction; stream >> seconds >> fraction; QDateTime transmitTime = QDateTime::fromMSecsSinceEpoch((quint64)seconds * 1000 - 2208988800000 + (quint64)fraction * 1000 / 0x100000000); // Set the system time to the NTP time m_time = transmitTime; #ifdef Q_OS_WIN setSystemTimeWindows(transmitTime); #elif defined(Q_OS_LINUX) setSystemTimeLinux(transmitTime); #endif emit dateTimeReceived(); } } #ifdef Q_OS_LINUX void NtpClient::setSystemTimeLinux(const QDateTime& dateTime) { QString dateTimeStr = dateTime.toString(Qt::ISODate); qDebug() << "Setting system time to" << dateTimeStr; // Set the system date and time using the "date" command QStringList arguments; arguments << "-s" << dateTimeStr; QProcess::execute("date", arguments); // Check that the system time was set correctly QDateTime systemTime = QDateTime::currentDateTime(); qint64 diffSeconds = dateTime.secsTo(systemTime); if (qAbs(diffSeconds) > 1) { qWarning() << "Failed to set system time to" << dateTimeStr; emit systemTimeSet(false); } else { qDebug() << "System time is now" << systemTime.toString(Qt::ISODate); emit systemTimeSet(true); } } #endif #ifdef Q_OS_WIN void NtpClient::setSystemTimeWindows(const QDateTime& dateTime) { SYSTEMTIME st; st.wYear = dateTime.date().year(); st.wMonth = dateTime.date().month(); st.wDay = dateTime.date().day(); st.wHour = dateTime.time().hour(); st.wMinute = dateTime.time().minute(); st.wSecond = dateTime.time().second(); st.wMilliseconds = dateTime.time().msec(); qDebug() << "Setting system time to" << dateTime.toString(Qt::ISODate); if (!SetSystemTime(&st)) { qWarning() << "Failed to set system time:" << GetLastError(); emit systemTimeSet(false); } else { QDateTime systemTime = QDateTime::fromSecsSinceEpoch(time(nullptr)); qDebug() << "System time is now" << systemTime.toString(Qt::ISODate); emit systemTimeSet(true); } } #endif
The code is compilable in both OS, but is not syncing system time.
Any Idea? What I am doing wrong? And is there any other way to do this?@Aviral-0 said in Hi I am trying to make NTP client which sync system time from NtpServer, and is Platform Independent for LINUX and WIN.:
m_udpSocket->connectToHost("server 0.in.pool.ntp.org", 123);
This not going to work. Since you do not check for a connected() signal (or equivalent) you will not have noticed this. The host name is invalid.
Where do you send a request?
My reading of the NTP UDP packet structure is that there is more data between the first byte and the various timestamp chunks.
And is there any other way to do this?
This particular wheel is well catered for on both Linux and Windows. Why reinvent it?