2

I got code from another user link

And i connect to: pool.ntp.org

But i cannot have any differences in time. (i need PERFECT sync with ntp server - then i will be happy)

My CODE:

time_t t = response.tx.to_time_t();
char *s = ctime(&t);

WSACleanup();

h_qtimeonStatusBar->setDateTime(QDateTime::fromTime_t(response.tx.to_time_t()));

But First i have this code:

getNTPTime(); //function above
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateTime())); // update time = current time from 'getNTPTime()' + 1 s
timer->start(0);
timer->setInterval(1000);

My diffrence is in miliseconds (max 1000) but it is really visible. My clock is litte slowly than ntp server (this is reliable information)

How to get rid of this differences ?

I try with that:

//func run after program start
{
        getNTPTime();
        QTimer *timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(updateTime()));
        timer->start(0);
        timer->setInterval(1000);
}


bool plemionabot1::getNTPTime(){
        using namespace std::chrono;
        WSADATA wsaData;
        DWORD ret = WSAStartup(MAKEWORD(2, 0), &wsaData);
        char *host = "pool.ntp.org"; /* Don't distribute stuff pointing here, it's not polite. */
        //char *host = "time.nist.gov"; /* This one's probably ok, but can get grumpy about request rates during debugging. */

        NTPMessage msg;
        /* Important, if you don't set the version/mode, the server will ignore you. */
        msg.clear();
        msg.version = 3;
        msg.mode = 3 /* client */;

        NTPMessage response;
        response.clear();

        int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
        sockaddr_in srv_addr;
        memset(&srv_addr, 0, sizeof(srv_addr));
        msg.dns_lookup(host, &srv_addr); /* Helper function defined below. */

        msg.sendto(sock, &srv_addr);
        auto t0 = high_resolution_clock::now();
        response.recv(sock);
        time_t t = response.tx.to_time_t();
        char *s = ctime(&t);

        WSACleanup();
        //QDateTime * tmp = new QDateTime;
        //tmp->setMSecsSinceEpoch(response.tx.seconds); // time is too much
        //h_qtimeonStatusBar->setDateTime(tmp->currentDateTime());
        h_qtimeonStatusBar->setDateTime(QDateTime::fromTime_t(response.tx.to_time_t())); // tą opcją wychodzi za mało
        auto t1 = high_resolution_clock::now();
        h_qtimeonStatusBar->setTime(h_qtimeonStatusBar->time().addMSecs(duration_cast<milliseconds>(t1-t0).count())); // time not enough
        return true;
}
Community
  • 1
  • 1
Thomas Banderas
  • 1,681
  • 1
  • 21
  • 43
  • I make time point after sendto, and second after recv - and add this to my time, but it still not enough.. `h_qtimeonStatusBar->setDateTime(QDateTime::fromTime_t(response.tx.to_time_t()));` i think this is fault of this, have You other idea? – Thomas Banderas Aug 05 '14 at 12:05

1 Answers1

2

From the QTimer documentation:

Accuracy and Timer Resolution

Timers will never time out earlier than the specified timeout value and they are not guaranteed to time out at the exact value specified. In many situations, they may time out late by a period of time that depends on the accuracy of the system timers.

You cannot rely on the QTimer to keep accurate time for you.

Instead, what you need to do is calculate the elapsed time since you last queried the NTP server. The elapsed time is based on your system clock, which might also drift, but that's not the same issue. Take the elapsed time since you queried the NTP server, and add it to the system clock time from the time you queried the NTP server, to get a better estimate of the current NTP time.

A better approach is to set up ntpd so that your system clock is automatically adjusted to the NTP time. Then your application doesn't have to worry about this, and you can simply display the system time.

Community
  • 1
  • 1
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • What i should use instead QTimer ? (And instead ntpd) From ntp i dont get any Miliseconds to synchronize it with my clock ? (i thought that i get seconds and miliseconds) And how to put these miliseconds to `QDateTime::fromTime_t()` ? – Thomas Banderas Aug 05 '14 at 01:41
  • You can still use QTimer to signal your application to update the clock on the screen. However, you have to do a calculation such as what I described above, instead of simply adding 1 s to the clock. – Greg Hewgill Aug 05 '14 at 01:42
  • And what about miliseconds from ntp server? – Thomas Banderas Aug 05 '14 at 01:48
  • Presumably you can get the milliseconds from the `tx.fraction` member of your message (as shown in the question you linked to). However, a better solution is still to install a real ntpd instead of managing this in your application. – Greg Hewgill Aug 05 '14 at 01:52
  • And can u tell me how to set time with miliseconds in QDateTime ? – Thomas Banderas Aug 05 '14 at 01:55
  • QDateTime has a [setMSecsSinceEpoch](http://qt-project.org/doc/qt-4.8/qdatetime.html#setMSecsSinceEpoch) method that you can use to set the milliseconds. – Greg Hewgill Aug 05 '14 at 01:58
  • Sorry again for question, but can You show me on example, how to get miliseconds from tx.fraction ? And put it to QDateTime like a me ? `h_qtimeonStatusBar->setDateTime(QDateTime::fromTime_t(response.tx.to_time_t()));` – Thomas Banderas Aug 05 '14 at 02:15
  • I would suppose you would use something like `setMSecsSinceEpoch(response.tx.seconds + (response.tx.fraction / 4294967296.0) * 1000)`. But I haven't tested this. – Greg Hewgill Aug 05 '14 at 02:18
  • i can ask what is this ? `4294967296.0` – Thomas Banderas Aug 05 '14 at 02:19
  • That is the numeric value of 2^32. – Greg Hewgill Aug 05 '14 at 02:20
  • I have [QDateTimeEdit](http://qt-project.org/doc/qt-4.8/qdatetimeedit.html) of course my fault, but i think that i can do it by QTime and setHMS , there is not `setMsecsSinceEpoch` method (can u show me a idea for `QDateTimeEdit`. I'm sleepy sorry ;( – Thomas Banderas Aug 05 '14 at 02:34
  • `setMSecsSinceEpoch` is a method of `QDateTime`. After you have set the time in your `QDateTime`, then you can pass that value to your `QDateTimeEdit`. – Greg Hewgill Aug 05 '14 at 02:35
  • So i make that: `QDateTime * tmp = new QDateTime; tmp->setMSecsSinceEpoch(response.tx.seconds + (response.tx.fraction / 4294967296.0) * 1000); h_qtimeonStatusBar->setDateTime(tmp->currentDateTime());` I'm shocked ;0 Now this time is a bit faster than real ntp time. – Thomas Banderas Aug 05 '14 at 02:45
  • Mhm at least i have miliseconds :D Hmm i saw ` tmp->setMSecsSinceEpoch(response.tx.seconds);` only THIS and `h_qtimeonStatusBar->setDateTime(tmp->currentDateTime());` give me time with MS ;0 – Thomas Banderas Aug 05 '14 at 02:47
  • What do you men "Instead, what you need to do is calculate the elapsed time since you last queried the NTP server." I connect only one time to NTP server when i initalize window (second code tell about this) , and when i got time i add to this 1s, per second – Thomas Banderas Aug 05 '14 at 03:00