QT ntp 并消除差异

Posted

技术标签:

【中文标题】QT ntp 并消除差异【英文标题】:QT ntp and getting rid of the differences 【发布时间】:2014-08-05 01:15:27 【问题描述】:

我从另一个用户那里得到了代码 link

我连接到:pool.ntp.org

但我不能在时间上有任何差异。 (我需要与 ntp 服务器完美同步 - 然后我会很高兴)

我的代码:

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

WSACleanup();

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

但首先我有这个代码:

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);

我的差异以毫秒为单位(最大 1000),但它确实是可见的。 我的时钟比 ntp 服务器慢一点(这是可靠的信息)

如何消除这种差异?

我试试看:

//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;

【问题讨论】:

我在 sendto 之后创建时间点,在 recv 之后创建第二个时间点 - 并将其添加到我的时间,但仍然不够。h_qtimeonStatusBar-&gt;setDateTime(QDateTime::fromTime_t(response.tx.to_time_t())); 我认为这是错误的,你有其他想法吗? 【参考方案1】:

来自QTimer documentation:

精度和计时器分辨率

计时器永远不会早于指定的超时值超时,并且不能保证在指定的确切值时超时。在许多情况下,它们可能会延迟一段时间,具体取决于系统计时器的准确性。

您不能依赖QTimer 来为您保持准确的时间。

相反,您需要做的是计算自您上次查询 NTP 服务器以来的经过时间。经过的时间取决于您的系统时钟,它也可能会漂移,但这不是同一个问题。获取自查询 NTP 服务器以来经过的时间,并将其添加到查询 NTP 服务器时的系统时钟时间,以更好地估计当前 NTP 时间。

更好的方法是设置 ntpd,以便您的系统时钟自动调整为 NTP 时间。那么你的应用程序就不用担心这个了,你可以简单的显示系统时间。

【讨论】:

我应该用什么代替 QTimer ? (而不是ntpd)从ntp我没有得到任何毫秒来与我的时钟同步? (我以为我得到秒和毫秒)以及如何将这些毫秒放入QDateTime::fromTime_t() 您仍然可以使用 QTimer 来通知您的应用程序以更新屏幕上的时钟。但是,您必须像我上面描述的那样进行计算,而不是简单地将 1 加到时钟上。 那么来自 ntp 服务器的毫秒数呢? 大概您可以从消息的tx.fraction 成员那里获得毫秒数(如您链接到的问题所示)。但是,更好的解决方案仍然是安装真正的 ntpd,而不是在您的应用程序中管理它。 你能告诉我如何在 QDateTime 中以毫秒为单位设置时间吗?

以上是关于QT ntp 并消除差异的主要内容,如果未能解决你的问题,请参考以下文章

如何消除与 Epoch 时间的时间差异?

NTP-网络时间协议

unix qt 与 windows qt的用法差异

unix qt 与 windows qt的用法差异

关于设置NTP

如何从 skimage.measure 中消除 compare_ssim 的 SSIM 图像输出中差异周围的边缘