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

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

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

  

1、QNetworkDatagram的使用

Qt提供了一個類QNetworkDatagram,用于在網(wǎng)絡上發(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)將網(wǎng)絡字節(jié)序的32位無符號整數(shù)轉換為主機字節(jié)序的32位無符號整數(shù)。

  下面是將網(wǎng)絡字節(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ā)和網(wǎng)絡阻塞等問題,我們可以使用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在網(wǎng)絡操作方面的強大實力,同時也為我們在實際應用中更好地使用Qt提供了不少思路。

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

標簽: 時頻百科

相關文章

DHCP服務器租約時間如何設置最優(yōu)?

DHCP服務器租約時間如何設置最優(yōu)?

  文章簡介:   DHCP(動態(tài)主機配置協(xié)議)是一種廣泛使用的網(wǎng)絡協(xié)議,在互聯(lián)網(wǎng)和企業(yè)內部網(wǎng)絡中被廣泛采用。DHCP服務器租約時間是網(wǎng)絡管理員需要配置的一個關鍵參數(shù),它決定了網(wǎng)絡中客戶端設備的IP地址、DNS服務器地址和網(wǎng)關的更新方式和時間。本文將從四個方面詳細闡述如何設置DHCP服務器租約時間最優(yōu)。    1、租約時間的定義與意義 租約時間是指DHCP服務向客戶端分配的IP地址的使用期限。在指定期間內,客...

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

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

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

Linux系統(tǒng)同步時間服務器地址方法及注意事項

Linux系統(tǒng)同步時間服務器地址方法及注意事項

  在Linux系統(tǒng)中,時間是一個很重要的概念,因為很多事情都是基于時間順序來完成的。為了保證Linux系統(tǒng)的時間精度和可靠性,我們往往需要將其與某個時間服務器進行同步。本文將從四個方面介紹Linux系統(tǒng)同步時間服務器地址的方法及注意事項。    1、查看當前系統(tǒng)時間 在同步服務器之前,我們需要先查看當前系統(tǒng)的時間,可以使用date命令來查看,該命令可以顯示當前時間以及一些其他信息,如下:...

Java實現(xiàn)服務器時間格式中心化修改方法詳解

Java實現(xiàn)服務器時間格式中心化修改方法詳解

  Java實現(xiàn)服務器時間格式中心化修改方法詳解文章概述:   本篇文章將詳細介紹Java如何實現(xiàn)服務器時間格式中心化修改方法。前期會先講解時間格式中心化的概念,再結合Java的相關實現(xiàn)技巧,分別從四個方面,即Java中的時間類提供的API、fastjson庫、Spring框架和MyBatis框架,對如何實現(xiàn)服務器時間格式中心化修改做出詳細的闡述。    1、Java中時間類的API Java提供的時間類在處...

Linux下同步NTP時間服務器的方法

Linux下同步NTP時間服務器的方法

  本篇文章主要是為給讀者介紹如何在Linux下同步NTP時間服務器的方法。通過這種方法,可以保證系統(tǒng)時間與正確的時間同步,從而避免在應用程序中使用錯誤的時間導致的問題。    1、安裝NTP服務器 在Linux系統(tǒng)中,我們可以使用NTP服務器來同步時間。首先,需要安裝NTP服務器,具體安裝方法根據(jù)不同的Linux系統(tǒng)而有所不同。例如,在Ubuntu系統(tǒng)中,可以通過以下命令來安裝:  ...

Delphi服務器時間為中心,探索時間管理與優(yōu)化的方法

Delphi服務器時間為中心,探索時間管理與優(yōu)化的方法

  本文以Delphi服務器時間為中心,探索時間管理與優(yōu)化的方法為主題,旨在幫助大家更好地應對日常開發(fā)中的時間管理問題,提高工作效率。    1、時間日歷的設計與使用 在Delphi中,可以通過創(chuàng)建日歷來幫助我們更好地管理時間。首先可以通過TDateTimePicker控件來創(chuàng)建時間選擇器,為用戶提供方便的時間選擇操作。其次,在日歷的設計中,可以通過設置不同顏色區(qū)分工作日、休息日等,讓用戶一目了然。...

Linux服務器時間設置與同步方法詳解

Linux服務器時間設置與同步方法詳解

  本文將圍繞Linux服務器時間設置與同步方法進行詳細闡述,涵蓋了系統(tǒng)時間、時區(qū)設置、NTP協(xié)議和手動時間同步四個方面。其中,系統(tǒng)時間和時區(qū)設置是時間同步的前提,NTP協(xié)議是常用的自動時間同步方式,手動時間同步則可以在NTP協(xié)議無法使用的情況下進行。通過本文的學習,您將掌握Linux服務器時間設置與同步的方法與技巧。    1、系統(tǒng)時間設置 系統(tǒng)時間是指硬件時鐘(RTC)所表示的時間,Linux系統(tǒng)啟動時會將其讀入內核并設置...

Java實現(xiàn)服務器響應時間監(jiān)控與優(yōu)化

Java實現(xiàn)服務器響應時間監(jiān)控與優(yōu)化

  隨著互聯(lián)網(wǎng)的發(fā)展,越來越多的應用程序需要運行在服務器上,給服務器端帶來了巨大的壓力。而服務器響應時間作為評估服務器性能的重要參數(shù),顯得尤為重要。本文將以"Java實現(xiàn)服務器響應時間監(jiān)控與優(yōu)化"為中心,從監(jiān)控、分析、優(yōu)化和實踐四個方面詳細闡述如何提高服務器響應時間,幫助讀者更好地了解提高服務器響應時間的方法和技巧。    1、監(jiān)控 服務器響應時間的監(jiān)控是保證服務器運行穩(wěn)定的關鍵,因此需要盡可能全面地監(jiān)控服...

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

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

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

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選項卡中進行設置。需要注意...

iPhone時鐘無法同步服務器時間的解決方案

iPhone時鐘無法同步服務器時間的解決方案

  本文將介紹iPhone時鐘無法同步服務器時間的解決方案。iPhone是廣受歡迎的智能手機,其時鐘功能對于日常生活而言,十分重要。然而,在使用iPhone時,有時我們會發(fā)現(xiàn)它的時鐘顯示并不準確,無法自動同步服務器時間。這樣一來,用戶將無法及時獲取到最新的時間信息,影響我們日常生活的安排。因此,本文將從多個方面為大家介紹如何解決這一問題。    1、檢查網(wǎng)絡連接 首先,我們需要檢查iPhone的網(wǎng)絡連接是否正常,因為iPhon...

LoL游戲服務器將進行維護,預計需要多長時間?

LoL游戲服務器將進行維護,預計需要多長時間?

  LoL游戲服務器即將進入維護階段,預計需要一段時間來完成此次維護。本文將從以下四個方面對LoL游戲服務器維護進行詳細闡述。    1、服務器升級 為提升LoL游戲服務器的性能和穩(wěn)定性,服務器需要進行升級。此次維護將對服務器的硬件和軟件進行更新,以確保LoL游戲服務器有更好的運行效果。   在服務器升級過程中,部分游戲功能可能無法正常使用,如排位賽和聯(lián)賽系統(tǒng),維護的時間將會持續(xù)數(shù)小時...

Linux服務器當前時間及時區(qū)查看方法

Linux服務器當前時間及時區(qū)查看方法

  Linux作為一個流行的服務器系統(tǒng),為系統(tǒng)管理員們提供了一個穩(wěn)定、可靠、高效的平臺。當前時間及時區(qū)對于服務器管理來說是非常重要的,在服務器運維和故障排查中也是一個非常關鍵的部分。本文將針對Linux服務器當前時間及時區(qū)查看方法進行詳細的闡述,從命令行操作、配置文件修改、圖形界面以及NTP服務等四個方面進行講解。    1、命令行操作 在Linux服務器上通過命令行操作是最基本、最常見的查看當前時間及時區(qū)的方法。...

Linux服務器被鎖后的自救時間分析

Linux服務器被鎖后的自救時間分析

  在Linux服務器使用過程中,有可能會發(fā)生被鎖的情況,這對服務器運維人員來說是一件非常麻煩的事情,因為一旦服務器被鎖,就需要進行自救,而自救的時間很大程度上決定了服務器恢復正常運行的速度,因此,針對Linux服務器被鎖后的自救時間,我們進行了詳細的分析和總結。    1、鎖定原因分析 服務器被鎖的原因有很多種,比如系統(tǒng)崩潰、系統(tǒng)資源占用等,只有分析出具體的原因,才能有針對性的進行自救。...