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

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

  使用Qt獲取NTP服務器時間是一個實用的功能,這樣可以使得程序在使用時更加準確,下面將會對這個功能進行詳細的闡述。

  

1、QNetworkDatagram的使用

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

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

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

  ```

  QByteArray requestData(48, 0);

  requestData[0] = 0x1b; // 設置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é)進行時間計算處理

  } else {

   qDebug() << "Request timeout";

  ```

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

  

2、將時間戳轉化為人類可讀的時間

獲取NTP服務器時間后,我們需要將時間戳轉化為人類可讀的時間??梢酝ㄟ^函數(shù)time_t ntohl(time_t netlong)將網絡字節(jié)序的32位無符號整數(shù)轉換為主機字節(jié)序的32位無符號整數(shù)。

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

  ```

  QByteArray data; // 從服務器獲取的數(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;

  ```

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

  

3、使用定時器獲取服務器時間

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

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

  ```

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

   // 進行時間戳處理

   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é)議的請求,并通過時間戳計算得到了當前的時間,并打印到控制臺上。

  

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

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

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

  ```

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

   // 進行時間戳處理

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

   }

   ~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機制與MainWindow類連接。在MainWindow類中,我們首先創(chuàng)建了一個QThreadPool對象,并在onStart()槽函數(shù)中,用服務器名字自動運行TimeRunnable的實例,并將currentTime信號與onTime槽函數(shù)連接,以便在收到服務器時間時輸出到控制臺上。

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

  總結:

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

  感謝您的閱讀,希望這篇文章能夠對您有所幫助!

標簽: 時頻百科

相關文章

“堅果云服務器維護時間及解決方案速度如何?”

“堅果云服務器維護時間及解決方案速度如何?”

  在互聯(lián)網時代,服務器的重要性不言而喻,因為它是網站運行的核心,也是提供服務的基礎。為了保障服務器的穩(wěn)定性和正常運行,堅果云服務器維護時間及解決方案的速度成為了用戶關注的熱點問題。那么,堅果云服務器維護時間及解決方案速度如何呢?本文將從不同角度詳細解答這個問題。    1、維護時間 堅果云提供365天24小時的運維服務支持,隨時隨地為客戶提供穩(wěn)定、安全的云服務器。在維護時間方面,堅果云會提前通知客戶,在維護期間確??蛻舻姆?..

Linux服務器時間變更記錄匯總與管理

Linux服務器時間變更記錄匯總與管理

  本文將圍繞Linux服務器時間變更記錄匯總與管理展開講述。Linux作為操作系統(tǒng)的一種,其服務器在運行過程中,時間的變更記錄和管理是一項極其重要的工作。本文將從時鐘同步、時區(qū)設置、時間服務管理、時間記錄與審計四個方面詳細闡述Linux服務器時間變更記錄匯總與管理的相關知識。    1、時鐘同步 Linux服務器時鐘同步,即系統(tǒng)時鐘與網絡時間協(xié)議(NTP)服務器時間的同步。正確的時鐘同步可以確保操作系統(tǒng)在進行時間戳記錄時,不...

Linux網絡時間服務器啟動指南

Linux網絡時間服務器啟動指南

  本文主要介紹Linux網絡時間服務器啟動指南,該指南詳細介紹了如何在 Linux 系統(tǒng)下配置并啟動網絡時間服務器。通過該指南,您可以了解如何將您的系統(tǒng)變成一個時間服務器,以便在局域網中被其它機器同步時間,同時保持時間的準確性和一致性。    1、NTP 簡介 NTP(Network Time Protocol)是一個用于同步網絡上計算機時間的協(xié)議,它能夠以高精度和高準確度將時鐘同步到全球各地數(shù)千個時鐘。在 Linux 中,...

mac服務器連接超時解決方案

mac服務器連接超時解決方案

  本文將為大家介紹如何解決mac服務器連接超時的問題。如果你使用蘋果電腦,連接到互聯(lián)網上的服務器時經常會出現(xiàn)連接超時的情況,那么本文將對你有所幫助。下面將從以下四個方面對mac服務器連接超時解決方案做詳細的闡述。    1、網絡連接方面 首先在我們連接服務器的時候,需要保證網絡的穩(wěn)定。如果在網絡較慢或者信號不好的情況下連接服務器,就容易出現(xiàn)連接超時的問題。在這種情況下,我們可以采用以下幾種方案來解決問題。...

Linux時間服務器與客戶端同步設置方法

Linux時間服務器與客戶端同步設置方法

  本文將為您詳細介紹Linux時間服務器與客戶端同步設置方法。我們將從NTP服務的概念、CentOS 7安裝配置、客戶端同步應用、以及本地時間設置四個方面進行闡述。    1、NTP服務的概念 NTP全稱為Network Time Protocol,是一個用來同步計算機時間的協(xié)議。NTP可以通過網絡將計算機的時鐘同步到UTC(協(xié)調世界時)還是TAI(國際原子時)。NTP協(xié)議經過多年的發(fā)展已經成為互聯(lián)網上最常用的時間同步協(xié)議,...

Linux服務器時間查看方法詳解

Linux服務器時間查看方法詳解

  在Linux服務器的管理過程中,時間的準確性是非常關鍵的。因此,了解如何正確查看服務器的時間是非常重要的。本文將從以下四個方面詳細介紹Linux服務器時間查看方法。    1、查看當前時間 要查看Linux服務器的當前時間,請使用date命令。該命令還可以用于設置服務器的時間。   要查看服務器的當前時間,請在終端輸入以下命令:   ...

App Store維護,應用升級等待,盡在掌握

App Store維護,應用升級等待,盡在掌握

  如果你是iPhone或iPad用戶,你一定不陌生App Store這個應用商店。在這個移動應用時代,應用商店也成為了智能手機的一個重要組成部分,它不僅提供了海量的應用程序,還可以為你提供便利的維護、升級等服務。今天,我們將以App Store維護、應用升級等待,盡在掌握為中心,從多個方面進行詳細闡述。    1、App Store維護是什么 在使用App Store時,我們經常會遇到一些問題,如連接不上、下載緩慢等等。這就...

Linux服務器時間切換方法詳解

Linux服務器時間切換方法詳解

  Linux服務器時間切換方法是Linux系統(tǒng)中非常重要的一個方面。在Linux服務器的日常運維中,時間同步一直都是一個比較麻煩的問題。由于Linux存在時鐘漂移現(xiàn)象等特點,這也就意味著我們不能夠完全依賴于硬件時鐘,需要我們經常性的進行時間同步操作,為了保證系統(tǒng)時間的準確性。因此,本文將對Linux服務器時間切換方法進行詳細闡述,涵蓋了NTP時間同步、手動修改系統(tǒng)時間等方面,方便讀者學習理解。    1、NTP時間同步 NT...

Dell服務器BIOS時間同步設置方法詳解

Dell服務器BIOS時間同步設置方法詳解

  本文將詳細講解Dell服務器BIOS時間同步設置方法。服務器在運行過程中,確保系統(tǒng)時間與真實時間同步,可以有效提高服務器系統(tǒng)的安全性和穩(wěn)定性。在Dell服務器中,設置BIOS時間同步方法簡單易懂,本文將從幾個方面介紹具體實現(xiàn)。    一、進入BIOS設置界面 在設置BIOS時間同步前,首先需要進入BIOS設置界面,操作方法如下:   1.服務器開機后,按照提示按鍵進入BIOS設置界...

《LOL服務器開通時間表及最新消息匯總》

《LOL服務器開通時間表及最新消息匯總》

  本文主要圍繞《LOL服務器開通時間表及最新消息匯總》展開論述,從四個方面分別闡述。    1、服務器開通時間表 服務器開通時間表是LOL游戲玩家們最關心的話題,因為開通時間表決定了他們何時可以進入游戲。根據(jù)最新消息,目前LOL官方已經公布了近期服務器開放時間表,具體如下:   6月1日-6月3日:原有服務器升級維護,不可登錄   6月4日-...

DNF服務器中斷!游戲大廳再次開放!

DNF服務器中斷!游戲大廳再次開放!

  近日,DNF服務器出現(xiàn)了中斷,導致廣大玩家無法順利進入游戲。但好消息是,經過多方努力,游戲大廳已經再次開放。本文將圍繞DNF服務器中斷及游戲大廳重新開放這一事件,從技術原因、影響、解決方案和對玩家的啟示四個方面進行詳細的闡述,希望能為廣大玩家提供一些有用的參考和啟示。    1、技術原因 DNF服務器中斷的根本原因是技術問題。游戲服務器是需要長期穩(wěn)定運行的,如果出現(xiàn)技術故障,則很可能導致服務器崩潰。造成DNF服務器中斷的具...

Linux服務器出廠時間查詢方法及注意事項

Linux服務器出廠時間查詢方法及注意事項

   Linux服務器出廠時間查詢方法及注意事項 本文將詳細介紹Linux服務器出廠時間的查詢方法,并提醒讀者關注注意事項。具體來說,我們將從以下四個方面進行闡述:    1、命令行查詢方法 在Linux服務器上,我們可以通過命令行來查詢出廠時間。具體使用的命令是dmidecode,這是一種硬件檢測工具。使用該命令時,需要輸入sudo dm...

NTP服務器時間同步配置指南

NTP服務器時間同步配置指南

  本文將圍繞NTP服務器時間同步配置指南展開,從四個方面對該主題進行詳細闡述。第一部分將介紹NTP的基本概念以及為什么需要進行時間同步;第二部分將介紹如何查看系統(tǒng)時間、系統(tǒng)時間的配置以及電腦時間的同步方法;第三部分將介紹如何使用Linux操作系統(tǒng)進行時間同步配置以及服務器和客戶端的關系;第四部分將介紹Windows操作系統(tǒng)下的時間同步配置和常見問題及解決方法。通過本文,希望讀者對NTP服務器時間同步配置擁有更深入的理解和掌握。   ...

HP服務器BIOS時間設置方法詳解

HP服務器BIOS時間設置方法詳解

  HP服務器BIOS時間設置方法是維護服務器時間一項十分重要的操作,通過對BIOS時間設置可以保證服務器運行的穩(wěn)定性,并且也會對系統(tǒng)記錄的事件產生影響,因此本文將詳細介紹HP服務器BIOS時間設置方法,從設置時間、時區(qū)、NTP服務器和時間保護四個方面進行闡述。    1、設置時間 設置時間是HP服務器BIOS時間設置的基礎,可以通過系統(tǒng)管理工具進入服務器BIOS設置界面,在Date and Time選項卡中進行設置。需要注意...

MC服務器時間固定設置指南

MC服務器時間固定設置指南

  本文將為廣大的MC服務器管理員們提供關于MC服務器時間固定設置的指南。在本文中,我們將從以下四個方面闡述MC服務器時間固定設置的全部內容,包括常見的具體實現(xiàn)方法。讀完本文,您將對MC服務器時間固定設置方面有更加深入全面的了解,從而更好地維護您的MC服務器。    1、服務器時間固定設置的概述 服務器時間固定設置是指為了維護MC服務器的穩(wěn)定性和公平性,將服務器的時間設置固定,防止其受到外部因素的干擾。在MC游戲中,物品的出現(xiàn)...