使用Qt獲取NTP服務(wù)器時間的方法及示例

admin2年前 (2023-07-12)時頻百科714

  使用Qt獲取NTP服務(wù)器時間是一個實(shí)用的功能,這樣可以使得程序在使用時更加準(zhǔn)確,下面將會對這個功能進(jìn)行詳細(xì)的闡述。

  

1、QNetworkDatagram的使用

Qt提供了一個類QNetworkDatagram,用于在網(wǎng)絡(luò)上發(fā)送和接收數(shù)據(jù)報(bào)。我們可以通過它發(fā)送一個NTP協(xié)議的請求。這個請求是一個48字節(jié)的數(shù)據(jù)報(bào),它的前48字節(jié)是0,第一個字節(jié)是17代表NTPv4,后面的字節(jié)里是一些控制信息。發(fā)送該數(shù)據(jù)報(bào)后,等待服務(wù)器返回48字節(jié)的應(yīng)答即可得到服務(wù)器的時間信息。

使用Qt獲取NTP服務(wù)器時間的方法及示例

  使用QNetworkDatagram類來實(shí)現(xiàn)發(fā)送和接收數(shù)據(jù)包的代碼如下:

  ```

  QByteArray requestData(48, 0);

  requestData[0] = 0x1b; // 設(shè)置NTP協(xié)議版本

  QNetworkDatagram datagram(requestData, QHostAddress("pool.ntp.org"), 123);

  QUdpSocket udpSocket;

  udpSocket.writeDatagram(datagram);

  if (udpSocket.waitForReadyRead(3000)) {

   QByteArray data;

   data.resize(udpSocket.pendingDatagramSize());

   udpSocket.readDatagram(data.data(), data.size());

   // 對獲取的數(shù)據(jù)字節(jié)進(jìn)行時間計(jì)算處理

  } else {

   qDebug() << "Request timeout";

  ```

  在上述代碼中,我們通過QByteArray對象建立了一個長度為48、且所有位都是0的數(shù)組,然后通過這個數(shù)組以及QHostAddress類創(chuàng)建了一個QNetworkDatagram對象,并將其發(fā)送到指定的主機(jī)地址和端口。如果在指定時間內(nèi)沒有收到來自服務(wù)器的應(yīng)答,則認(rèn)為該次請求超時。

  

2、將時間戳轉(zhuǎn)化為人類可讀的時間

獲取NTP服務(wù)器時間后,我們需要將時間戳轉(zhuǎn)化為人類可讀的時間。可以通過函數(shù)time_t ntohl(time_t netlong)將網(wǎng)絡(luò)字節(jié)序的32位無符號整數(shù)轉(zhuǎn)換為主機(jī)字節(jié)序的32位無符號整數(shù)。

  下面是將網(wǎng)絡(luò)字節(jié)序的64位時間戳轉(zhuǎn)換為人可讀的時間的代碼:

  ```

  QByteArray data; // 從服務(wù)器獲取的數(shù)據(jù)

  unsigned long long NTP_TIMESTAMP_DELTA = 2208988800ull; // 參考時間:1900年1月1日

  time_t high = ntohl(*((uint32_t*)&data[40])) - NTP_TIMESTAMP_DELTA;

  time_t low = ntohl(*((uint32_t*)&data[44]));

  time_t ntp_time = (high << 32) low;

  QDateTime utc(QDate(1900, 1, 1), QTime(0, 0, 0), Qt::UTC);

  QDateTime current(utc.addSecs(ntp_time));

  qDebug() << "Current time is" << current;

  ```

  在上述代碼中,我們首先將從服務(wù)器獲取的64位時間戳分別存儲在high和low變量中,然后將它們拼接成一個新的64位時間戳ntp_time。接著,我們根據(jù)參考時間以及加上ntp_time計(jì)算出QDateTime對象current表示當(dāng)前時間。

  

3、使用定時器獲取服務(wù)器時間

我們可以使用Qt中的QTimer定時器類,并在定時器的槽函數(shù)中實(shí)現(xiàn)NTP協(xié)議的請求和計(jì)算NTP服務(wù)器時間的過程。

  下面的代碼演示了如何使用QTimer類來獲取NTP服務(wù)器時間:

  ```

  void MainWindow::startTimer()

   QTimer *timer = new QTimer(this);

   connect(timer, &QTimer::timeout, this, &MainWindow::onTimer);

   timer->start(1000); // 每隔1秒執(zhí)行一次onTimer()

  void MainWindow::onTimer()

   QByteArray requestData(48, 0);

   requestData[0] = 0x1b;

   QNetworkDatagram datagram(requestData, QHostAddress("pool.ntp.org"), 123);

   QUdpSocket udpSocket;

   udpSocket.writeDatagram(datagram);

   if (udpSocket.waitForReadyRead(3000)) {

   QByteArray data;

   data.resize(udpSocket.pendingDatagramSize());

   udpSocket.readDatagram(data.data(), data.size());

   // 進(jìn)行時間戳處理

   unsigned long long NTP_TIMESTAMP_DELTA = 2208988800ull;

   time_t high = ntohl(*((uint32_t*)&data[40])) - NTP_TIMESTAMP_DELTA;

   time_t low = ntohl(*((uint32_t*)&data[44]));

   time_t ntp_time = (high << 32) low;

   QDateTime utc(QDate(1900, 1, 1), QTime(0, 0, 0), Qt::UTC);

   QDateTime current(utc.addSecs(ntp_time));

   qDebug() << "Current time is" << current;

   } else {

   qDebug() << "Request timeout";

   }

  ```

  在上述代碼中,我們首先在startTimer()函數(shù)中創(chuàng)建了一個QTimer對象,并將它與onTimer()槽函數(shù)連接并定時啟動。在onTimer函數(shù)中,我們使用了前面提到的QNetworkDatagram類發(fā)送了一個NTP協(xié)議的請求,并通過時間戳計(jì)算得到了當(dāng)前的時間,并打印到控制臺上。

  

4、使用并發(fā)框架多線程并發(fā)地獲取服務(wù)器時間

對于高并發(fā)和網(wǎng)絡(luò)阻塞等問題,我們可以使用Qt提供的QThreadPool類實(shí)現(xiàn)多線程并發(fā)獲取NTP服務(wù)器時間。

  下面的代碼展示了如何使用QThreadPool和QRunnable類來實(shí)現(xiàn)多線程并發(fā)獲取NTP服務(wù)器時間:

  ```

  class TimeRunnable : public QRunnable

  public:

   TimeRunnable(const QString &server) : _server(server) {}

   void run() override {

   QByteArray requestData(48, 0);

   requestData[0] = 0x1b;

   QNetworkDatagram datagram(requestData, QHostAddress(_server), 123);

   QUdpSocket udpSocket;

   udpSocket.writeDatagram(datagram);

   if (udpSocket.waitForReadyRead(3000)) {

   QByteArray data;

   data.resize(udpSocket.pendingDatagramSize());

   udpSocket.readDatagram(data.data(), data.size());

   // 進(jìn)行時間戳處理

   unsigned long long NTP_TIMESTAMP_DELTA = 2208988800ull;

   time_t high = ntohl(*((uint32_t*)&data[40])) - NTP_TIMESTAMP_DELTA;

   time_t low = ntohl(*((uint32_t*)&data[44]));

   time_t ntp_time = (high << 32) low;

   QDateTime utc(QDate(1900, 1, 1), QTime(0, 0, 0), Qt::UTC);

   QDateTime current(utc.addSecs(ntp_time));

   emit currentTime(current);

   }

   }

  signals:

   void currentTime(const QDateTime &);

  };

  class MainWindow : public QMainWindow

   Q_OBJECT

  public:

   MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {

   _pool.setMaxThreadCount(10); // 設(shè)置線程池最大線程數(shù)

   }

   ~MainWindow() {}

  public slots:

   void onTime(const QDateTime ¤t) {

   qDebug() << "Current time is" << current;

   }

   void onStart() {

   for (const auto &server : _servers) {

   TimeRunnable *runnable = new TimeRunnable(server);

   connect(runnable, &TimeRunnable::currentTime, this, &MainWindow::onTime);

   _pool.start(runnable);

   }

   }

  private:

   QVector _servers{"pool.ntp.org", "cn.ntp.org.cn", "time.windows.com"};

   QThreadPool _pool;

  };

  ```

  在上述代碼中,我們創(chuàng)建了一個名為TimeRunnable的類,其中包含發(fā)送和接收NTP請求的代碼,并通過signals和slots機(jī)制與MainWindow類連接。在MainWindow類中,我們首先創(chuàng)建了一個QThreadPool對象,并在onStart()槽函數(shù)中,用服務(wù)器名字自動運(yùn)行TimeRunnable的實(shí)例,并將currentTime信號與onTime槽函數(shù)連接,以便在收到服務(wù)器時間時輸出到控制臺上。

  經(jīng)過上述改進(jìn),我們可以同時對多個NTP服務(wù)器進(jìn)行請求,增加了代碼的魯棒性并加快了時間獲取速度。

  總結(jié):

  使用Qt獲取NTP服務(wù)器時間是一個強(qiáng)大的功能,可以在許多實(shí)際應(yīng)用中發(fā)揮重要作用。在本文中我們提到了4個方法:使用QNetworkDatagram發(fā)送和接收請求、將時間戳轉(zhuǎn)化為人類可讀的時間、使用定時器獲取時間和使用并發(fā)框架獲取NTP服務(wù)器時間等。這些方法體現(xiàn)了Qt在網(wǎng)絡(luò)操作方面的強(qiáng)大實(shí)力,同時也為我們在實(shí)際應(yīng)用中更好地使用Qt提供了不少思路。

  感謝您的閱讀,希望這篇文章能夠?qū)δ兴鶐椭?

標(biāo)簽: 時頻百科

相關(guān)文章

FTP服務(wù)器如何查看文件修改時間?

FTP服務(wù)器如何查看文件修改時間?

  FTP服務(wù)器是一個常用的文件傳輸協(xié)議,但是我們有時候需要查看文件的修改時間,本文將從四個方面詳細(xì)講述FTP服務(wù)器如何查看文件修改時間。    1、服務(wù)器端查看文件修改時間 服務(wù)器端是FTP傳輸?shù)臄?shù)據(jù)中轉(zhuǎn)站,我們可以在服務(wù)器端查看文件的修改時間,具體步驟如下:   第一步:連接FTP服務(wù)器,輸入用戶名和密碼并登錄;   第二步:切換到對應(yīng)的目...

Linux獲取時間同步服務(wù)器的方法及步驟

Linux獲取時間同步服務(wù)器的方法及步驟

  在現(xiàn)代的計(jì)算機(jī)系統(tǒng)中,時間同步是非常關(guān)鍵的。服務(wù)器需要同步時間以確保日志記錄和其他時間相關(guān)的功能正常工作。 Linux正在被廣泛使用,并且是數(shù)據(jù)中心中主要的操作系統(tǒng)。因此,在Linux上獲取時間同步服務(wù)器的方法及步驟對于Linux用戶來說是非常重要的。    1、NTP(Network Time Protocol) 獲取時間同步服務(wù)器的方法之一是使用NTP(Network Time Protocol)。它是一個用于計(jì)算機(jī)系...

LOL外服服務(wù)器開放時間及注意事項(xiàng)

LOL外服服務(wù)器開放時間及注意事項(xiàng)

  近年來,隨著《英雄聯(lián)盟》(LOL)在全球范圍內(nèi)的火爆,越來越多的玩家開啟了外服游戲的模式。而對于首次嘗試外服游戲的玩家來說,要想在游戲中順利前行,首先必須熟悉LOL外服服務(wù)器的開放時間和注意事項(xiàng)。    1、外服服務(wù)器開放時間 LOL外服服務(wù)器開放時間通常有周一、周三、周五、周六四個時間段,每個時間段在當(dāng)?shù)貢r間下午2點(diǎn)至第二天凌晨7點(diǎn)之間。不過這個時間段在不同的外服服務(wù)器上也有所不同,需要玩家根據(jù)自己所在的國家和地區(qū)選擇相...

CentOS NTP時間同步問題解決方案

CentOS NTP時間同步問題解決方案

  近年來,由于科技的迅速發(fā)展,計(jì)算機(jī)領(lǐng)域的應(yīng)用變得越來越廣泛。很多企業(yè)廠商使用計(jì)算機(jī)技術(shù)來提高工作效率,同時也帶來了新的問題,其中之一便是時鐘同步問題。    1、CentOS NTP時間同步問題的現(xiàn)象 在使用 CentOS 的過程中,經(jīng)常會出現(xiàn)服務(wù)器時鐘不同步的問題,導(dǎo)致服務(wù)器的時間與其他服務(wù)器的時間不一致,這樣會影響到一些必須要時間同步的應(yīng)用,例如數(shù)據(jù)庫的同步備份工作。具體表現(xiàn)為:...

GPS NTP網(wǎng)絡(luò)時間服務(wù)器:精準(zhǔn)時間同步之首選

GPS NTP網(wǎng)絡(luò)時間服務(wù)器:精準(zhǔn)時間同步之首選

  隨著現(xiàn)代科技的飛速發(fā)展,人們對于時間的精準(zhǔn)度要求也越來越高,而GPS NTP網(wǎng)絡(luò)時間服務(wù)器作為精準(zhǔn)同步時間的首選,成為了現(xiàn)代科技領(lǐng)域不可或缺的一部分。本文將從GPS NTP網(wǎng)絡(luò)時間服務(wù)器的四個方面對其精確同步時間的重要性和優(yōu)勢進(jìn)行詳細(xì)闡述。    1、精準(zhǔn)性 GPS NTP網(wǎng)絡(luò)時間服務(wù)器的最大優(yōu)勢就是時間同步精準(zhǔn)度高。由于GPS衛(wèi)星的高度和軌道固定,所有GPS NTP時間服務(wù)器接收到的信號是來自相同的地球同步時間(UTC)...

Eclipse服務(wù)器超時時間設(shè)置方法大全,詳細(xì)步驟教程完善指南

Eclipse服務(wù)器超時時間設(shè)置方法大全,詳細(xì)步驟教程完善指南

  本篇文章主要向您介紹Eclipse服務(wù)器超時時間設(shè)置方法大全,詳細(xì)步驟教程完善指南,通過對以下四個方面的詳細(xì)闡述,幫助您解決此問題:    1、服務(wù)器超時時間是什么?為什么要設(shè)置? 首先,我們需要明確什么是服務(wù)器超時時間。在網(wǎng)絡(luò)通信過程中,客戶端向服務(wù)器發(fā)送請求,服務(wù)器接收到請求后進(jìn)行相應(yīng)處理,如果服務(wù)器在一定時間內(nèi)沒有響應(yīng)客戶端的請求,那么客戶端會認(rèn)為服務(wù)器已經(jīng)無響應(yīng),超時時間就是指服務(wù)器在一定時間內(nèi)沒有響應(yīng)的時間。超時...

Docker部署時間服務(wù)器,快速簡便地同步時間!

Docker部署時間服務(wù)器,快速簡便地同步時間!

  在互聯(lián)網(wǎng)時代,時間同步非常重要,因?yàn)楸姸嗟膽?yīng)用和服務(wù)都需要準(zhǔn)確的時間。Docker是一個非常流行的容器化技術(shù),可以快速部署和管理容器應(yīng)用程序。因此,使用Docker部署時間服務(wù)器可以快速簡便地同步時間,本文將從以下四個方面對Docker部署時間服務(wù)器進(jìn)行詳細(xì)的闡述。    1、Docker安裝 首先,需要安裝Docker??梢酝ㄟ^官方網(wǎng)站下載并安裝Docker。在Linux系統(tǒng)中,可以使用以下命令安裝:...

Linux命令行:查看服務(wù)器時間,掌握服務(wù)流程的核心。

Linux命令行:查看服務(wù)器時間,掌握服務(wù)流程的核心。

  本文將從以下四個方面闡述如何通過Linux命令行查看服務(wù)器時間,從而掌握服務(wù)流程的核心。    1、核心命令 Linux系統(tǒng)中,最基本的查看服務(wù)器時間的命令是date。該命令能夠精確地顯示當(dāng)前系統(tǒng)的日期和時間。在命令行輸入date后,系統(tǒng)將會返回當(dāng)前的日期和時間,其格式為:“星期 月 日 時:分:秒 時區(qū) 年”。   該命令的常見參數(shù)有-u、-r和-I,分別表示使用協(xié)調(diào)世界時間、顯...

Linux服務(wù)器時間同步方法簡介

Linux服務(wù)器時間同步方法簡介

  本文將詳細(xì)介紹Linux服務(wù)器時間同步方法,包括4個方面的內(nèi)容:NTP時間同步、手動設(shè)置日期時間、定時同步時間以及時區(qū)設(shè)置。先介紹NTP時間同步,并與其他同步方法做對比分析。然后,介紹手動設(shè)置日期時間,包括常用的date命令及其參數(shù)的使用方法。接著,講解如何定時同步時間,包括crontab命令及其用法。最后,介紹如何設(shè)置時區(qū),包括查看當(dāng)前時區(qū)和設(shè)置不同時區(qū)的方法。    1、NTP時間同步 NTP(Network Time...

JavaScript客戶端和服務(wù)器時間戳不一致,如何解決?

JavaScript客戶端和服務(wù)器時間戳不一致,如何解決?

  JavaScript是一種用于編程的高級語言,可用于在客戶端和服務(wù)器端執(zhí)行腳本。但是,當(dāng)在這兩個環(huán)境中處理時間時,存在JavaScript客戶端和服務(wù)器時間戳不一致的問題。這個問題可能會導(dǎo)致很多問題,如數(shù)據(jù)不同步、計(jì)算錯誤等。因此,在本文中,我們將從四個方面闡述JavaScript客戶端和服務(wù)器時間戳不一致的問題,以及如何解決這些問題。    1、時間戳的概念 在JavaScript中,時間戳是指自1970年1月1日0時0...

Dell原廠服務(wù)器服務(wù)時間統(tǒng)計(jì)及保障措施

Dell原廠服務(wù)器服務(wù)時間統(tǒng)計(jì)及保障措施

  本文主要圍繞"Dell原廠服務(wù)器服務(wù)時間統(tǒng)計(jì)及保障措施"展開,探究Dell在保障客戶服務(wù)時間方面的措施及具體實(shí)施情況。全文主要分為四個部分,在廣度和深度上進(jìn)行了充分的探討,以期為讀者提供全面且實(shí)用的參考。    1、服務(wù)時間的定義 在正式了解Dell的服務(wù)時間統(tǒng)計(jì)和保障措施之前,有必要先明確服務(wù)時間的概念。服務(wù)時間通常是指企業(yè)為客戶或用戶提供服務(wù)的時間范圍,其中包括正常工作時間、節(jié)假日、下班時間等,這是...

Linux下實(shí)時查看服務(wù)器時間的命令大全

Linux下實(shí)時查看服務(wù)器時間的命令大全

  文章概括:   本文將從多個方面詳細(xì)介紹Linux下實(shí)時查看服務(wù)器時間的命令大全,內(nèi)容涵蓋四個方面:date命令、hwclock命令、ntpdate命令和timedatectl命令。通過本文的閱讀,讀者可以深入了解這些命令的使用方法和注意事項(xiàng),從而更好地管理服務(wù)器時間。    1、date命令 date命令是Linux系統(tǒng)下最常用的查看時間的命令之一。它可以獲取系統(tǒng)當(dāng)前的日期和時間,并且可以通過參數(shù)的方式...

2015年DNF服務(wù)器時間表及更新計(jì)劃

2015年DNF服務(wù)器時間表及更新計(jì)劃

  在2015年,DNF的服務(wù)器時間表及更新計(jì)劃引起了許多玩家們的極大關(guān)注。為了正式開始游戲,玩家需要對于服務(wù)器時間表及更新計(jì)劃有一個清晰的了解,并且隨時跟進(jìn)更新。在本文中,我們將從四個方面對2015年DNF服務(wù)器時間表及更新計(jì)劃進(jìn)行詳細(xì)的闡述,幫助玩家們了解這些內(nèi)容。    1、新的職業(yè)、新的副本 在2015年DNF的服務(wù)器時間表及更新計(jì)劃中,最重要的一件事情就是推出了新的職業(yè)與新的副本。新的職業(yè)包括了女鬼劍士、男漆黑之翼等...

MES服務(wù)器維修時長分析與解決方案

MES服務(wù)器維修時長分析與解決方案

  本文將探討MES服務(wù)器維修時長分析與解決方案。MES服務(wù)器的穩(wěn)定運(yùn)行是企業(yè)生產(chǎn)管理的重要基礎(chǔ),但服務(wù)器出現(xiàn)故障不可避免。本文將從四個方面,即故障檢測、維修預(yù)測、維修保養(yǎng)和維修實(shí)施,分析MES服務(wù)器維修時長的問題,并提出相應(yīng)解決方案。    1、故障檢測 MES服務(wù)器的故障可能有多種原因,如硬件故障、軟件故障、網(wǎng)絡(luò)故障等。在實(shí)施故障檢測時,需要對MES服務(wù)器進(jìn)行全面的檢查和診斷,確定故障點(diǎn),進(jìn)而制定相應(yīng)的故障處理方案。...

Linux服務(wù)器時間檢查方法大全!

Linux服務(wù)器時間檢查方法大全!

  Linux服務(wù)器是一個重要的工具,因此確保服務(wù)器時間的準(zhǔn)確性非常重要。一個不準(zhǔn)確的時鐘可能會導(dǎo)致大量的問題,從日志不正確到計(jì)劃任務(wù)無法正常運(yùn)行。本文將詳細(xì)介紹Linux服務(wù)器時間檢查方法,包括硬件時鐘和系統(tǒng)時鐘的調(diào)整、NTP服務(wù)器的配置以及與NTP服務(wù)器的同步操作。    1、硬件時鐘和系統(tǒng)時鐘的調(diào)整 Linux服務(wù)器有兩個時鐘:硬件時鐘和系統(tǒng)時鐘。硬件時鐘是在服務(wù)器的主板上直接運(yùn)行的,它的日期和時間被記錄在CMOS存儲器...