QtC++ 中使用 qtwebsocket 開源庫實現基于websocket的本地服務開發詳解

前言

當前實時通信功能越來越受到重視,無論是在線聊天、實時數據監控還是多人協作工具,都離不開高效、穩定的實時通信技術。WebSocket 作為一種全雙工通信協議,為實時通信提供了良好的解決方案。而在 QtC++ 開發環境中,qtwebsocket 開源庫則是實現 WebSocket 通信的一個非常有效幫手。本文將詳細介紹 如何使用qtwebsocket 庫來實現本地服務端的開發。?

一、qtwebsocket 開源庫介紹?

1.1 基本概念?

qtwebsocket 是一個基于 Qt 框架的開源庫,它實現了 WebSocket 協議,允許在客戶端和服務器之間建立持久的連接,進行雙向的數據傳輸。WebSocket 協議不同于傳統的 HTTP 協議,HTTP 是一種無狀態的、單向的請求 - 響應協議,而 WebSocket 則是一種持久化的協議,一旦建立連接,客戶端和服務器就可以隨時向對方發送數據,大大提高了實時通信的效率。?
qtwebsocket 庫充分利用了 Qt 的特性,如信號與槽機制,使得開發者能夠更加便捷地處理 WebSocket 通信過程中的各種事件,如連接建立、數據接收、連接斷開等。它支持標準的 WebSocket 協議(RFC 6455),可以與各種遵循該標準的 WebSocket 客戶端進行通信。?

1.2 特點和優勢?

  • 基于 Qt 框架:qtwebsocket 庫深度集成了 Qt 框架,開發者可以利用 Qt 豐富的類庫和工具,快速構建出跨平臺的 WebSocket 應用程序。Qt 本身具有良好的跨平臺特性,使得使用 qtwebsocket 開發的服務端可以輕松運行在 Windows、Linux、macOS 等多種操作系統上。?
  • 簡單易用:該庫提供了簡潔明了的 API 接口,通過 Qt 的信號與槽機制來處理各種事件,開發者無需深入了解 WebSocket 協議的底層細節,就能夠快速上手進行開發。例如,當有新的客戶端連接時,服務端會發出相應的信號,開發者只需關聯對應的槽函數即可進行處理。?
  • 高效穩定:qtwebsocket 庫經過了廣泛的測試和實際應用的檢驗,具有較高的效率和穩定性。它能夠有效地處理多個客戶端的并發連接,保證數據傳輸的及時性和準確性。?
  • 支持多種數據類型:該庫支持文本數據和二進制數據的傳輸,滿足不同場景下的數據通信需求。無論是簡單的文本消息,還是復雜的二進制數據(如圖片、音頻等),都可以通過 qtwebsocket 庫進行傳輸。?
  • 開源免費:qtwebsocket 是開源軟件,遵循開源協議,開可以自由地使用、修改和分發該庫,降低了開發成本。?

1.3 核心類和函數?

1.3.1 QWebSocketServer:

QWebSocketServer是 qtwebsocket 庫中用于創建 WebSocket 服務端的核心類。它負責監聽客戶端的連接請求,管理已建立的連接。?
主要函數:?

  • QWebSocketServer(const QString &serverName, SslMode secureMode, QObject *parent = nullptr):構造函數,用于創建一個 WebSocket 服務端實例。其中,serverName是服務端的名稱,secureMode指定是否使用 SSL 加密,parent是父對象。?
  • listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0):開始監聽指定地址和端口上的連接請求。address默認為任意地址,port默認為 0(隨機端口)。如果監聽成功,返回true,否則返回false。?
  • newConnection():信號,當有新的客戶端連接到服務端時發出。開發者可以關聯該信號到自定義的槽函數,在槽函數中獲取新連接的客戶端對象。?
  • close():關閉服務端,停止監聽連接請求,并斷開所有已建立的連接。?

1.3.2 QWebSocket:

QWebSocket代表一個 WebSocket 連接,既可以是客戶端連接,也可以是服務端接收到的客戶端連接。在服務端開發中,當有新的客戶端連接時,QWebSocketServer 會創建一個 QWebSocket 對象來表示該連接。?
主要函數:?

  • sendTextMessage(const QString &message):向對方發送文本消息。?
  • sendBinaryMessage(const QByteArray &data):向對方發送二進制消息。?
  • textMessageReceived(const QString &message):信號,當接收到文本消息時發出。?
  • binaryMessageReceived(const QByteArray &data):信號,當接收到二進制消息時發出。?
  • disconnected():信號,當連接斷開時發出。?
  • close():關閉當前連接。?

1.3.2 QHostAddress:

用于表示網絡地址,在服務端開發中,用于指定服務端監聽的地址。例如,QHostAddress::Any表示監聽所有可用的網絡接口。?

1.3.3 quint16:

這里專門對一個無符號 16 位整數類型的quint16說明,只是想說,它在這里主要用于表示端口號,WebSocket 服務端需要監聽一個特定的端口來接收客戶端的連接請求。?

二、本地服務端開發準備?

2.1 開發環境搭建?

  • 安裝 Qt:可以從 Qt 官方網站(https://www.qt.io/)下載 Qt 安裝包,根據自己的操作系統選擇合適的版本。在安裝過程中,需要選擇相應的 Qt 版本(建議選擇 5.10 及以上版本,因為這些版本對 qtwebsocket 庫的支持更加完善)和組件,確保勾選了 “Qt WebSockets” 組件,這樣在安裝完成后就會自動包含 qtwebsocket 庫。?
  • 配置 Qt Creator:安裝完成后,打開 Qt Creator 集成開發環境。在 Qt Creator 中,需要確保項目的構建套件(Kit)配置正確,選擇安裝好的 Qt 版本作為構建套件。?
  • 驗證 qtwebsocket 庫是否可用:可以創建一個新的 Qt 控制臺應用程序項目,在項目文件(.pro 文件)中添加QT += websockets,然后嘗試包含 qtwebsocket 庫的頭文件(如#include 、#include ),如果沒有出現編譯錯誤,則說明 qtwebsocket 庫已經正確安裝并可以使用。?

2.2 相關知識儲備?

  • WebSocket 協議基礎:雖然 qtwebsocket 庫已經封裝了 WebSocket 協議的底層細節,但了解 WebSocket 協議的基本原理還是很有必要的,如握手過程、數據幀格式等,這有助于更好地理解和使用 qtwebsocket 庫進行開發,以下再進行詳細介紹。?

三、本地服務端開發全過程?

3.1 創建 Qt 項目?

打開 Qt Creator,點擊 “文件”->“新建文件或項目”。?
在彈出的對話框中,選擇 “應用程序”->“Qt Widgets 應用程序”(也可以根據實際需求選擇其他類型的應用程序,如控制臺應用程序),然后點擊 “選擇”。?
進入項目名稱和路徑設置頁面,輸入項目名稱(如 “LocalWebSocketServer”),選擇項目保存的路徑,點擊 “下一步”。?
在 “類信息” 頁面,設置主窗口類的名稱(如 “MainWindow”),基類選擇 “QMainWindow”,點擊 “下一步”,“下一步”, “下一步”。。。?
最后點擊 “完成”,創建項目。?

3.2 配置項目文件(.pro 文件)?

在創建好的項目中,找到項目文件(LocalWebSocketServer.pro),打開并添加以下內容:

QT       += core gui websocketsgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = LocalWebSocketServer
TEMPLATE = appSOURCES += \main.cpp \mainwindow.cppHEADERS += \mainwindow.hFORMS += \mainwindow.ui

其中,QT += websockets是關鍵,用于告訴 Qt 構建系統在項目中包含 qtwebsocket 庫。?

3.3 設計服務端界面

如果創建的是 Qt Widgets 應用程序,可以通過 Qt Designer 來設計服務端的界面,用于顯示服務端的運行狀態、客戶端連接信息、接收和發送的消息等。例如,咱就簡單的添加以下控件:?

  • QLabel:用于顯示服務端的狀態(如 “未啟動”、“正在監聽” 等)、監聽的地址和端口等信息。?
  • QTextEdit:用于顯示日志信息,如客戶端連接、斷開連接、消息接收等。?
  • QPushButton:用于啟動服務端、停止服務端、向客戶端發送消息等操作。?
  • QLineEdit:用于輸入要發送的消息內容或指定客戶端。?

3.4 實現服務端核心功能?

  • 包含必要的頭文件:在 mainwindow.h 文件中,包含 qtwebsocket 庫的相關頭文件和其他需要的頭文件。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QWebSocketServer>
#include <QWebSocket>
#include <QList>
#include <QString>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_startServerBtn_clicked();void on_stopServerBtn_clicked();void on_sendMessageBtn_clicked();void onNewConnection();void onTextMessageReceived(const QString &message);void onDisconnected();private:Ui::MainWindow *ui;QWebSocketServer *m_webSocketServer;QList<QWebSocket *> m_clients;void logMessage(const QString &message);
};#endif // MAINWINDOW_H
  • 初始化服務端對象:在 mainwindow.cpp 文件的構造函數中,初始化 QWebSocketServer 對象,并關聯相關的信號與槽。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QHostAddress>
#include <QDebug>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow),m_webSocketServer(nullptr)
{ui->setupUi(this);setWindowTitle("本地WebSocket服務端");// 初始化服務端狀態ui->statusLabel->setText("服務端未啟動");ui->startServerBtn->setEnabled(true);ui->stopServerBtn->setEnabled(false);ui->sendMessageBtn->setEnabled(false);// 關聯按鈕點擊信號與槽函數connect(ui->startServerBtn, &QPushButton::clicked, this, &MainWindow::on_startServerBtn_clicked);connect(ui->stopServerBtn, &QPushButton::clicked, this, &MainWindow::on_stopServerBtn_clicked);connect(ui->sendMessageBtn, &QPushButton::clicked, this, &MainWindow::on_sendMessageBtn_clicked);
}MainWindow::~MainWindow()
{stopServer();delete ui;
}
  • 實現啟動服務端功能:在啟動服務端的槽函數中,創建 QWebSocketServer 實例,并調用 listen () 函數開始監聽客戶端的連接請求。
void MainWindow::on_startServerBtn_clicked()
{// 停止已有的服務端(如果存在)if (m_webSocketServer) {stopServer();}// 創建WebSocket服務端,不使用SSL加密m_webSocketServer = new QWebSocketServer(QStringLiteral("Local WebSocket Server"),QWebSocketServer::NonSecureMode, this);// 監聽所有地址,端口號為8080if (m_webSocketServer->listen(QHostAddress::Any, 8080)) {ui->statusLabel->setText(QStringLiteral("服務端正在監聽,地址:%1,端口:%2").arg(m_webSocketServer->serverAddress().toString()).arg(m_webSocketServer->serverPort()));logMessage("服務端啟動成功");// 關聯新連接信號connect(m_webSocketServer, &QWebSocketServer::newConnection,this, &MainWindow::onNewConnection);ui->startServerBtn->setEnabled(false);ui->stopServerBtn->setEnabled(true);ui->sendMessageBtn->setEnabled(true);} else {ui->statusLabel->setText(QStringLiteral("服務端啟動失敗:%1").arg(m_webSocketServer->errorString()));logMessage("服務端啟動失敗:" + m_webSocketServer->errorString());delete m_webSocketServer;m_webSocketServer = nullptr;}
}
  • 處理新連接:當有新的客戶端連接到服務端時,QWebSocketServer 會發出 newConnection () 信號,在對應的槽函數中獲取客戶端對象,并關聯該客戶端的消息接收和斷開連接信號。
void MainWindow::onNewConnection()
{QWebSocket *pSocket = m_webSocketServer->nextPendingConnection();if (!pSocket) {return;}logMessage(QStringLiteral("新客戶端連接,地址:%1,端口:%2").arg(pSocket->peerAddress().toString()).arg(pSocket->peerPort()));// 關聯客戶端的信號connect(pSocket, &QWebSocket::textMessageReceived,this, &MainWindow::onTextMessageReceived);connect(pSocket, &QWebSocket::disconnected,this, &MainWindow::onDisconnected);// 將客戶端添加到客戶端列表m_clients << pSocket;
}
  • 處理接收的消息:當服務端接收到客戶端發送的文本消息時,會觸發 textMessageReceived () 信號,在槽函數中處理接收到的消息,如顯示在日志中,或向其他客戶端轉發等。
void MainWindow::onTextMessageReceived(const QString &message)
{QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());if (pSender) {logMessage(QStringLiteral("收到來自 %1:%2 的消息:%3").arg(pSender->peerAddress().toString()).arg(pSender->peerPort()).arg(message));// 可以在這里將消息轉發給其他客戶端foreach (QWebSocket *pClient, m_clients) {if (pClient != pSender && pClient->state() == QAbstractSocket::ConnectedState) {pClient->sendTextMessage(message);}}}
}
  • 處理連接斷開:當客戶端與服務端斷開連接時,會發出 disconnected () 信號,在槽函數中將該客戶端從客戶端列表中移除,并釋放資源。
void MainWindow::onDisconnected()
{QWebSocket *pSocket = qobject_cast<QWebSocket *>(sender());if (pSocket) {logMessage(QStringLiteral("客戶端斷開連接,地址:%1,端口:%2").arg(pSocket->peerAddress().toString()).arg(pSocket->peerPort()));m_clients.removeAll(pSocket);pSocket->deleteLater();}
}
  • 實現停止服務端功能:在停止服務端的槽函數中,關閉服務端,斷開所有客戶端的連接,并釋放相關資源。
void MainWindow::on_stopServerBtn_clicked()
{stopServer();
}void MainWindow::stopServer()
{if (m_webSocketServer) {// 關閉所有客戶端連接foreach (QWebSocket *pClient, m_clients) {pClient->close();pClient->deleteLater();}m_clients.clear();// 關閉服務端m_webSocketServer->close();delete m_webSocketServer;m_webSocketServer = nullptr;ui->statusLabel->setText("服務端已停止");logMessage("服務端已停止");ui->startServerBtn->setEnabled(true);ui->stopServerBtn->setEnabled(false);ui->sendMessageBtn->setEnabled(false);}
}
  • 實現發送消息功能:服務端可以向連接的客戶端發送消息,在發送消息的槽函數中,獲取輸入的消息內容,并發送給指定的客戶端或所有客戶端。
void MainWindow::on_sendMessageBtn_clicked()
{QString message = ui->messageLineEdit->text();if (message.isEmpty()) {logMessage("消息內容不能為空");return;}// 向所有連接的客戶端發送消息foreach (QWebSocket *pClient, m_clients) {if (pClient->state() == QAbstractSocket::ConnectedState) {pClient->sendTextMessage(message);}}logMessage("發送消息:" + message);ui->messageLineEdit->clear();
}
  • 日志顯示功能:實現一個輔助函數,用于將各種事件和消息顯示在日志控件中。
void MainWindow::logMessage(const QString &message)
{ui->logTextEdit->appendPlainText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + " " + message);
}

3.5 編譯和運行?

  • 點擊 Qt Creator 中的 “構建”->“構建項目”(或按下 Ctrl+B),對項目進行編譯。如果編譯過程中出現錯誤,根據錯誤提示進行修改。?
  • 編譯成功后,點擊 “運行” 按鈕(或按下 Ctrl+R),運行服務端程序。此時,服務端程序啟動,點擊 “啟動服務端” 按鈕,服務端開始監聽 8080 端口。?

3.6 測試服務端?

  • 使用 WebSocket 客戶端工具:可以使用一些在線的 WebSocket 測試工具(如https://wstool.js.org/)或專門的客戶端軟件來測試服務端。在客戶端工具中,輸入服務端的地址(如 ws://localhost:8080),點擊連接按鈕。?
  • 發送消息:連接成功后,在客戶端工具中輸入消息并發送,服務端的日志控件中會顯示收到的消息,同時客戶端也會收到服務端轉發的消息(如果服務端實現了轉發功能)。?
  • 多客戶端測試:打開多個客戶端工具,都連接到服務端,然后從一個客戶端發送消息,觀察其他客戶端是否能收到消息,以測試服務端的多客戶端處理和消息轉發功能。?
  • 斷開連接測試:關閉客戶端工具,觀察服務端的日志是否顯示客戶端斷開連接的信息。?

3.7 優化和擴展?

  • 錯誤處理:在實際開發中,需要加強錯誤處理,如處理服務端監聽失敗、客戶端連接異常、消息發送失敗等情況,提高服務端的穩定性。?
  • 配置化:將服務端的監聽地址、端口等參數配置到配置文件中,使得服務端可以靈活配置,而不需要修改代碼重新編譯。?
  • 認證和授權:對于一些需要安全驗證的應用,可以在客戶端連接時進行認證和授權,只有通過驗證的客戶端才能與服務端進行通信。?
  • 數據加密:如果對數據安全性要求較高,可以使用 SSL/TLS 對 WebSocket 連接進行加密,qtwebsocket 庫支持 SSL 模式,只需在創建 QWebSocketServer 時選擇 SecureMode,并配置相應的證書即可。?
  • 性能優化:對于需要處理大量并發連接的服務端,可以進行性能優化,如使用多線程處理客戶端連接、限制單個客戶端的消息頻率等。?

四、qtwebsocket 庫的實際應用案例?

4.1 實時聊天系統?

在實時聊天系統中,服務端需要處理多個客戶端的連接,接收客戶端發送的聊天消息,并將消息轉發給其他客戶端。使用 qtwebsocket 庫可以很方便地實現這一功能。服務端通過 QWebSocketServer 監聽客戶端連接,當有新客戶端連接時,將其加入客戶端列表。當收到某個客戶端的消息時,遍歷客戶端列表,將消息轉發給其他所有在線的客戶端,實現實時聊天功能。?

4.2 實時數據監控系統?

在工業監控、環境監測等領域,需要實時將設備采集的數據發送到監控中心。服務端可以使用 qtwebsocket 庫接收設備(客戶端)發送的實時數據,并將數據展示在監控界面上,同時可以向設備發送控制指令。通過 WebSocket 的實時通信特性,能夠保證數據的及時性和準確性,滿足實時監控的需求。?

4.3 多人協作編輯工具?

在多人協作編輯文檔、表格等工具中,多個用戶可以同時編輯同一個文件,每個用戶的修改需要實時同步給其他用戶。服務端使用 qtwebsocket 庫接收用戶的修改操作消息,然后將這些消息廣播給其他用戶,使得所有用戶的界面保持一致,實現多人實時協作。?

五、常見問題及解決方法?

5.1 服務端啟動失敗?

  • 端口被占用:這是最常見的一種情況,如果服務端啟動時提示端口被占用,可以嘗試更換一個未被占用的端口。可以通過命令行工具(如 Windows 的 netstat -ano 命令)查看端口的占用情況,然后在服務端代碼中修改監聽的端口號。?
  • 權限不足:在某些操作系統上,監聽低于 1024 的端口需要管理員權限。如果服務端需要監聽這些端口,可以以管理員身份運行服務端程序,或者更換為高于 1024 的端口。?
  • 網絡配置問題:檢查服務端的監聽地址是否正確,如果設置為特定的網絡接口地址,確保該網絡接口正常工作。可以嘗試使用 QHostAddress::Any 監聽所有地址。?

5.2 客戶端無法連接到服務端?

  • 服務端未啟動:確保服務端已經成功啟動并正在監聽指定的端口,在一些真正的項目中,實際上是需要在開發一個監聽服務,專門用于監查服務端是否在正常工作。?
  • 地址或端口錯誤:檢查客戶端連接時使用的地址和端口是否與服務端的監聽地址和端口一致。?
  • 防火墻設置:防火墻可能會阻止客戶端與服務端之間的連接。可以暫時關閉防火墻進行測試,如果問題解決,則需要在防火墻中添加規則,允許 WebSocket 通信的端口通過。?
  • 跨域問題:這也是一個很常見的問題,如果客戶端是網頁應用,可能存在跨域問題。在服務端需要設置適當的跨域資源共享(CORS)頭部,允許客戶端所在的域名進行連接。?

5.3 消息發送或接收異常?

  • 消息格式錯誤:確保客戶端和服務端發送的消息格式一致,如文本消息使用正確的編碼,二進制消息的格式符合雙方的約定。?
  • 連接狀態異常:在發送消息前,檢查客戶端或服務端的連接狀態是否為已連接(QAbstractSocket::ConnectedState),只有在連接狀態下才能發送消息。?
  • 消息過大:WebSocket 協議對單條消息的大小有一定的限制,如果消息過大,可能會導致發送或接收失敗。可以將大消息分割成多個小消息進行發送,在接收端再進行合并。?

六、總結

本文詳細介紹了 qtwebsocket 開源庫,包括其基本概念、特點優勢和核心類函數,并全程講解了使用該庫實現本地服務端開發的過程。
qtwebsocket 庫憑借其基于 Qt 框架、簡單易用、高效穩定等特點,為 QtC++ 開發者提供了便捷的 WebSocket 通信解決方案。通過本文的學習,開發者可以快速上手使用 qtwebsocket 庫進行本地服務端開發,滿足實時通信的需求。?
同時,結合 Qt 的其他技術,如 Qt Quick、Qt Network 等,開發者可以構建出更加豐富、高效的實時應用程序。例如,使用 Qt Quick 構建跨平臺的客戶端界面,結合 qtwebsocket 庫實現與服務端的實時通信,為用戶提供更好的體驗。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/92544.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/92544.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/92544.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小程序實時保存優化

背景。避免數據存儲后丟失。要求實時保存。問題&#xff1a;保存時出現卡斷&#xff0c;輸入的內容會被抹除。問題原因。輸入頻繁速度塊&#xff0c;會影響cpu處理速度。解決方案。用戶停止輸入500ms后開始保存&#xff0c;否則不保存。這里是保存方法&#xff1a;當500ms以內有…

國產化Excel處理組件Spire.XLS教程:使用 C# 將 DataTable 導出為 Excel 文件

在 C# 中將 DataTable 導出為 Excel 文件&#xff0c;是 .NET 開發中常見的任務&#xff0c;廣泛應用于報表生成、日志導出、系統間數據共享等場景。通過使用獨立的組件庫&#xff0c;開發者可以輕松將 DataTable 數據寫入 Excel 文件&#xff0c;并應用格式設置&#xff0c;生…

C語言學習筆記——編譯和鏈接

目錄1 C程序的執行流程2 翻譯環境2.1 預編譯2.2 編譯2.2.1 詞法分析2.2.2 語法分析2.2.3 語法分析2.3 匯編2.4 鏈接1 C程序的執行流程 用戶編寫好的C程序不能直接被計算機識別并執行&#xff0c;在執行前&#xff0c;要先將源文件和頭文件進行編譯&#xff0c;生成目標文件&am…

Flink-1.19.0源碼詳解9-ExecutionGraph生成-后篇

《Flink-1.19.0源碼詳解8-ExecutionGraph生成-前篇》前篇已從Flink集群端調度開始解析ExecutionGraph生成的源碼&#xff0c;解析了ExecutionGraph的ExecutionJobVertex節點、ExecutionVertex節點、IntermediateResult數據集、IntermediateResultPartition數據集分區與封裝Task…

19、閾值分割+blob分析

目錄 一、仿射變換 1.變換矩陣 2.在矩陣的基礎上添加各種變換形式 3.開始變換 4.計算變換矩陣參數 新算子 二、閾值分割 新算子 三、blob分析案例 1.焊點 2.石頭 3.木材 4.車牌 5.骰子 新算子 一、仿射變換 1.變換矩陣 // 產生仿射變換矩陣hom_mat2d_identity…

破解 Django N+1 查詢困境:使用 select_related 與 prefetch_related 實踐指南

破解 Django N+1 查詢困境:使用 select_related 與 prefetch_related 實踐指南 開篇引入 數據庫查詢性能常常是 Web 應用性能瓶頸中的重中之重。Django ORM 以簡潔直觀的 API 層將 Python 代碼與數據庫打通,卻也可能因默認的惰性加載帶來 N+1 查詢問題,造成不必要的網絡往…

深入解析K-means聚類:從原理到調優實戰

一、聚類分析與K-means的核心價值在無監督學習領域&#xff0c;聚類分析是探索數據內在結構的核心技術。?K-means算法因其簡潔高效成為最廣泛使用的聚類方法&#xff0c;在客戶分群、圖像壓縮、生物信息學等領域應用廣泛。其核心目標是將數據集劃分為K個簇&#xff0c;實現“簇…

數據結構基礎:哈希表、排序和查找算法

目錄 一、哈希表 1.哈希算法 2.哈希碰撞 3.哈希表 4.哈希表相關操作 哈希表插入 哈希表遍歷 元素查找 哈希表銷毀 二、排序算法 1. 排序算法對比 2. 排序算法實現 冒泡排序 選擇排序 插入排序 希爾排序 快速排序 三、查找算法 1. 查找算法對比 2. 查找算法實…

Linux內核參數調優:為K8s節點優化網絡性能

在高并發微服務環境中&#xff0c;網絡性能往往成為K8s集群的瓶頸。本文將深入探討如何通過精細化的Linux內核參數調優&#xff0c;讓你的K8s節點網絡性能提升30%以上。引言&#xff1a;為什么網絡調優如此重要&#xff1f;作為一名在生產環境中維護過數千節點K8s集群的運維工程…

全家桶” 戰略如何重塑智能服務標準?無憂秘書 AI + 智腦 + 數字人協同模式的底層架構解析

在數字化浪潮的推動下&#xff0c;企業對智能化服務的需求日益增長。然而&#xff0c;單一的技術或產品往往難以滿足復雜場景下的多樣化需求。近年來&#xff0c;“全家桶”戰略成為科技行業的一大趨勢&#xff0c;通過整合多維度技術與服務&#xff0c;為企業提供全方位的支持…

前端后端之爭?JavaScript和Java的特性與應用場景解析

一、名字相似&#xff0c;本質迥異 1.1 歷史淵源與命名背景 在編程世界中&#xff0c;很少有兩種語言像JavaScript和Java這樣&#xff0c;僅僅因為名字的相似性就引發了無數初學者的困惑。然而&#xff0c;這種相似性純屬巧合——或者說是一種營銷策略的產物。 JavaScript誕…

【文獻分享】Machine learning models提供數據和代碼

數據輸入及前期信息&#xff1a;ChronoGauge 需要一個基因表達矩陣&#xff0c;其中包括來自多個時間進程 RNA-測序實驗的觀測數據&#xff0c;用于訓練&#xff0c;并且需要有關每個基因在連續光照&#xff08;LL&#xff09;條件下經過光暗&#xff08;LD&#xff09;周期調整…

PHP MySQL Delete 操作詳解

PHP MySQL Delete 操作詳解 引言 在Web開發中&#xff0c;數據庫是存儲和管理數據的重要工具。PHP作為一種流行的服務器端腳本語言&#xff0c;與MySQL數據庫結合使用可以高效地處理數據。本文將詳細介紹PHP中如何使用DELETE語句刪除MySQL數據庫中的數據。 什么是DELETE語句&am…

計組-大/小端存放區別

在計算機系統中&#xff0c;大端存放&#xff08;Big-Endian&#xff09;和小端存放&#xff08;Little-Endian&#xff09;是兩種不同的多字節數據存儲方式&#xff0c;主要區別在于字節在內存中的排列順序。理解它們對底層編程&#xff08;如網絡通信、二進制文件處理、硬件交…

線程同步相關知識

文章目錄一、線程同步的核心目標二、線程安全的判定條件三、同步方式一&#xff1a;synchronized 關鍵字1. 同步代碼塊2. 同步方法四、鎖的釋放與不釋放場景1. 自動釋放鎖的場景2. 不會釋放鎖的場景五、同步方式二&#xff1a;ReentrantLock&#xff08;顯式鎖&#xff09;1. 核…

Armoury Crate無法通過BIOS卸載

設備&#xff1a;天選4 Armoury Crate窗口反復彈出影響使用體驗&#xff0c;但無法通過BIOS關閉該怎么辦&#xff1f;本文以天選4為例提供解決方案。 Step1&#xff1a;進入服務支持官網 Armoury Crate-服務支持 下滑點擊”查看更多” 下載安裝卸載工具 得到Armoury_Crate_Un…

如何將視頻轉為GIF格式,3大視頻轉為GIF工具

在社交媒體和即時通訊盛行的當下&#xff0c;GIF 動圖以其獨特的魅力備受青睞。它能夠生動地捕捉視頻中的精彩瞬間&#xff0c;憑借體積小巧、無需復雜加載且可循環播放的特性&#xff0c;成為了人們在網絡交流中表達情感、分享趣事的得力工具。無論是制作詼諧幽默的表情包&…

開發避坑指南(22):Vue3響應式編程中this綁定機制與解決方案

錯誤信息 TypeError: Cannot read properties of undefined (reading find) TypeError: r.vnode.el.querySelector is not a function報錯背景 vue2項目升級到vue3后&#xff0c;原來的代碼報錯。 報錯代碼computed: {/** 計算列的顯示與隱藏*/columnVisible() {return functio…

AI學習筆記三十五:實時傳輸視頻

若該文為原創文章&#xff0c;轉載請注明原文出處。 目的是實現視頻的傳輸&#xff0c;只是個demo. 程序分為兩部分&#xff0c;視頻接收端和視頻發送端。 一、視頻接收端流程分析 主要流程&#xff1a; 初始化配置&#xff1a; 設置UDP端口&#xff08;5001&#xff09;和緩…

【ArcGIS】分區統計中出現Null值且Nodata無法忽略的問題以及shp擦除(erase)的使用——以NDVI去水體為例

需求 已有某地NDVI柵格、行政區shp以及水體shp&#xff0c;計算每個行政區的平均NDVI 問題 1.如果不剔除水體 負值NDVI會把平均值拉低 且水體NDVI并不全為負 需要通過shp剔除&#xff0c;Mask掩膜是提取水體本身而不是剩余部分 2.使用分區統計工具&#xff08;Zonal statis…