Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Hi I am trying to make NTP client which sync system time from NtpServer, and is Platform Independent for LINUX and WIN.
Forum Updated to NodeBB v4.3 + New Features

Hi I am trying to make NTP client which sync system time from NtpServer, and is Platform Independent for LINUX and WIN.

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 4 Posters 408 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Aviral 0A Offline
    Aviral 0A Offline
    Aviral 0
    wrote on last edited by Aviral 0
    #1

    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 0A C 2 Replies Last reply
    0
    • Aviral 0A Aviral 0

      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 0A Offline
      Aviral 0A Offline
      Aviral 0
      wrote on last edited by
      #2

      @Aviral-0 @jsulm Any Suggestions?

      jsulmJ JonBJ 2 Replies Last reply
      0
      • Aviral 0A Aviral 0

        @Aviral-0 @jsulm Any Suggestions?

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @Aviral-0 Did you do any debugging? You are basically asking to debug your code. I'm not going to analyse all this code before you do some debugging...

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1
        • Aviral 0A Aviral 0

          @Aviral-0 @jsulm Any Suggestions?

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @Aviral-0
          As @jsulm says.

          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.

          1 Reply Last reply
          1
          • Aviral 0A Aviral 0

            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?

            C Offline
            C Offline
            ChrisW67
            wrote on last edited by
            #5

            @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?

            1 Reply Last reply
            1

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved