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

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

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

  

1、QNetworkDatagram的使用

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

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

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

  ```

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

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

  } else {

   qDebug() << "Request timeout";

  ```

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

  

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

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

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

  ```

  QByteArray data; // 從服務器獲取的數據

  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。接著,我們根據參考時間以及加上ntp_time計算出QDateTime對象current表示當前時間。

  

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

我們可以使用Qt中的QTimer定時器類,并在定時器的槽函數中實現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()函數中創(chuàng)建了一個QTimer對象,并將它與onTimer()槽函數連接并定時啟動。在onTimer函數中,我們使用了前面提到的QNetworkDatagram類發(fā)送了一個NTP協(xié)議的請求,并通過時間戳計算得到了當前的時間,并打印到控制臺上。

  

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

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

  下面的代碼展示了如何使用QThreadPool和QRunnable類來實現多線程并發(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); // 設置線程池最大線程數

   }

   ~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()槽函數中,用服務器名字自動運行TimeRunnable的實例,并將currentTime信號與onTime槽函數連接,以便在收到服務器時間時輸出到控制臺上。

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

  總結:

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

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

標簽: 時頻百科

相關文章

Linux服務器時間轉換問題排查與解決方法

Linux服務器時間轉換問題排查與解決方法

  本文將介紹在Linux服務器上進行時間轉換時可能會遇到的問題,并提供排查和解決問題的方法。    1、時區(qū)設置錯誤 在服務器上設置時區(qū)時,如果設置錯誤會導致時間轉換問題。例如,服務器所在的時區(qū)可能是美國中部時間(CST),但是系統(tǒng)的時區(qū)設置成了東部時間(EST)。如果將UTC(世界協(xié)調時間)轉換為CST,所得到的結果會比實際時間早1小時。   要解決這個問題,可以通過以下命令查看當...

“將服務器時間設為中心,提高系統(tǒng)管理效率”

“將服務器時間設為中心,提高系統(tǒng)管理效率”

  隨著互聯網的發(fā)展,各種網站、應用程序以及云服務的需求不斷擴大,服務器的管理也日益復雜。如何提高系統(tǒng)管理的效率,成為了服務器管理人員必須面對的問題。而將服務器時間設為中心,則是一個非常重要的方法。    1、時間同步的重要性 服務器時間同步是服務器管理中的一個非?;A的工作。對于服務器來說,準確同步時間并非一件簡單的事情,服務器遇到的復雜情況,比如硬件故障、多臺服務器之間時間同步等問題,都會影響到時間同步的精度。...

CentOS搭建時間服務器詳細教程

CentOS搭建時間服務器詳細教程

  本文主要介紹如何在CentOS操作系統(tǒng)上搭建時間服務器。時間服務器可以提供精確的日期和時間,對于需要準確同步時間的應用場景非常重要。    1、安裝NTP服務 首先需要安裝NTP服務,這可以通過在終端中輸入以下命令來實現:   sudo yum install ntp   安裝成功后,接下來需要進行一些配置。在/etc/ntp.conf文件...

“以Jboss服務器時間為準確基準,如何修改服務器系統(tǒng)時間?”

“以Jboss服務器時間為準確基準,如何修改服務器系統(tǒng)時間?”

  本文將介紹如何以Jboss服務器時間為準確基準,對服務器系統(tǒng)時間進行修改。服務器時間的準確性對于系統(tǒng)的運行和日志記錄至關重要,因此及時修正并保持準確是非常重要的。    1、修改服務器時間的前提準備 在進行服務器時間的修改前,需要先做好以下準備工作:   1)確保您擁有操作系統(tǒng)的管理員賬戶權限,以便進行時間修改操作;   2)確定您的服務器...

Linux構建NTP時間服務器指南

Linux構建NTP時間服務器指南

  本文是一篇關于以Linux系統(tǒng)為基礎構建NTP時間服務器的指南。通過闡述該指南,讀者將會了解如何使用Linux系統(tǒng)構建NTP時間服務器并確保系統(tǒng)時間的精準性,從而保證各種應用程序和計算機之間的時間同步。全文分為四個方面,包括NTP時間服務器的基本概念、構建NTP服務器的步驟、NTP服務器的安全性以及如何測試和調試NTP服務器。接下來我們將依次進行詳細闡述。    1、基本概念 NTP是“網絡時間協(xié)議”的簡稱,它是用于在計算...

GPRS模塊與時間服務器的聯合,實現精準時鐘同步

GPRS模塊與時間服務器的聯合,實現精準時鐘同步

  隨著物聯網技術的不斷發(fā)展,如何進行精準時鐘同步已經成為了一個不可忽視的問題。而GPRS模塊與時間服務器的聯合,可以幫助我們實現了這一目標。本文將詳細闡述GPRS模塊與時間服務器的聯合實現精準時鐘同步的原理及方法。    1、GPRS模塊的作用及原理 GPRS模塊是一款常見的無線通信模塊,可以通過通信網絡實現數據的傳輸。在精準時鐘同步中,GPRS模塊起到了將時間信息傳輸到終端設備的作用。...

ATR安泰鏈服務器注冊時間及其意義

ATR安泰鏈服務器注冊時間及其意義

  ATR安泰鏈是一種區(qū)塊鏈技術,其注冊時間為2019年6月,這一時間標志著ATR安泰鏈正式進入市場,并且在進一步通過技術創(chuàng)新實現更多應用。ATR安泰鏈的注冊時間具有重要的意義,這個意義將從四個方面進行詳細闡述。    1、ATR安泰鏈注冊時間的意義 首先,ATR安泰鏈的注冊時間代表著區(qū)塊鏈技術的更新換代。ATR安泰鏈不僅承襲著比特幣的基本思想,同時在技術層面上進行了創(chuàng)新,加入了共識算法、智能合約、跨鏈通訊等新技術,在性能、安...

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

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

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

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

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

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

Epic服務器更新時間表:最新公告和計劃更新

Epic服務器更新時間表:最新公告和計劃更新

  本文主要討論Epic服務器的更新時間表,涵蓋最新公告和計劃更新,將從以下四個方面進行詳細闡述:一、Epic服務器的背景介紹;二、Epic服務器的最新公告;三、Epic服務器的當前計劃更新;四、對Epic服務器更新時間表的總結和歸納。    一、Epic服務器的背景介紹 Epic服務器是美國Epic Games公司提供的在線游戲服務,為全球玩家提供穩(wěn)定、高效、安全的游戲環(huán)境,是全球最受歡迎的游戲服務之一。Epic服務器在游戲...

“服務器時間同步異常導致dcdiag誤報問題研究”

“服務器時間同步異常導致dcdiag誤報問題研究”

  本文主要介紹“服務器時間同步異常導致dcdiag誤報問題研究”。為了更好地闡述這個問題,本文將從四個方面進行詳細的闡述:問題背景、問題根源、問題分析、問題解決。通過本文的介紹,希望能夠更好地幫助讀者理解和解決這個問題。    1、問題背景 在進行服務器管理時,我們常常遇到dcdiag誤報的問題。通過對系統(tǒng)診斷發(fā)現,問題的原因是服務器時間同步異常。服務器時間同步異常會導致系統(tǒng)的各種問題,比如認證失敗、路由錯誤、文件傳輸失敗等...

Java實現獲取服務器響應時間的方法及注意事項

Java實現獲取服務器響應時間的方法及注意事項

  本文將以Java實現獲取服務器響應時間的方法及注意事項為中心,全文分成多個自然段,每個自然段字數控制均勻一些,詳細闡述獲取服務器響應時間的方法以及需要注意的事項。    1、基本原理 獲取服務器響應時間是測量服務器的計算能力的重要指標之一。服務端需要把客戶端的請求處理完畢后,才能給客戶端響應結果,因此,獲取服務器響應時間的關鍵在于如何確定客戶端發(fā)出請求和服務端響應導致本地程序得到結果所花費的時間。...

iOS客戶端與服務器時間校對方案

iOS客戶端與服務器時間校對方案

  本文將從四個方面詳細闡述iOS客戶端與服務器時間校對方案,包括時間校對的問題,iOS客戶端與服務器時間校對方案的實現方法,該方案的優(yōu)缺點以及未來是否有更好的解決方案,同時對整篇文章進行總結歸納。    1、時間校對的問題 在iOS應用中,時間是一項非常關鍵的因素。應用可能需要檢查當前的時間或是定時某些操作。如果應用的時間不正確,很可能會出現各種不兼容或其他問題。在iOS應用中,有兩個主要問題需要解決:設備時間和網絡時間。...

NTPD時間服務器的搭建與配置

NTPD時間服務器的搭建與配置

  本文介紹了NTPD時間服務器的搭建與配置。首先,我們會介紹NTPD時間服務器的定義及其作用。然后,我們會探討如何在Linux操作系統(tǒng)中安裝和配置NTPD時間服務器,包括服務器的配置和客戶端的配置。接著,我們將介紹NTPD時間服務器的優(yōu)點和缺點。最后,我們會對全文進行總結和歸納。    1、NTPD時間服務器的定義及作用 NTPD是Network Time Protocol Daemon的縮寫,是一種網絡時間協(xié)議守護進程,它...

NBA2K19服務器關閉時間公布,玩家們的游戲時光將結束

NBA2K19服務器關閉時間公布,玩家們的游戲時光將結束

  近日,NBA2K19官方宣布了其服務器關閉時間,這也意味著玩家們的游戲時光將即將結束。這一消息對于NBA2K19的鐵粉們來說,無疑是一個巨大的打擊。他們已經花費了大量的時間和金錢在這個游戲中,而現在他們必須準備面對游戲的關閉。對于這一切,我們進行全面的探討,以便更加深入地了解這個事件對玩家和游戲產業(yè)的潛在影響。    1、關閉服務器帶來的影響 對于那些沉迷于NBA2K19的玩家們來說,這個消息無疑是一個巨大的打擊,因為游戲...