Qt UDP Socket的具體使用
1 -> 概述
UDP(User Datagram Protocol,用戶數(shù)據(jù)報協(xié)議)是一種無連接的、不可靠但高效的數(shù)據(jù)傳輸協(xié)議。它不保證數(shù)據(jù)包的順序、完整性或可達性,但由于沒有建立連接和確認機制,傳輸速度較快,適合實時性要求高、允許少量丟包的應用場景,如音視頻流、在線游戲、DNS查詢等。
Qt 作為一個跨平臺的C++應用程序框架,對網(wǎng)絡編程提供了良好的封裝。Qt Network 模塊中的 QUdpSocket 類提供了UDP協(xié)議的網(wǎng)絡通信能力,使開發(fā)者能夠輕松實現(xiàn)基于UDP的數(shù)據(jù)收發(fā)功能。
2 -> Qt UDP Socket 核心類
在Qt中實現(xiàn)UDP通信主要涉及兩個核心類:
2.1 ->QUdpSocket
- 表示一個UDP socket,用于綁定端口、接收和發(fā)送數(shù)據(jù)報。
- 繼承自
QAbstractSocket,屬于Qt Network模塊。 - 支持IPv4和IPv6。
2.2 ->QNetworkDatagram
- 表示一個UDP數(shù)據(jù)報,封裝了數(shù)據(jù)內(nèi)容、發(fā)送/接收方的IP地址和端口信息。
- 提供了便捷的方法來獲取和構(gòu)造數(shù)據(jù)報。
3 -> 核心API詳解
3.1 ->QUdpSocket類的主要方法
3.1.1 ->bind(const QHostAddress &address, quint16 port)
- 功能:將socket綁定到指定的IP地址和端口。
- 參數(shù):
address:綁定的IP地址,如QHostAddress::Any表示綁定到所有可用地址。port:綁定的端口號。
- 返回值:布爾類型,表示綁定是否成功。
- 說明:綁定后,socket開始監(jiān)聽該端口的數(shù)據(jù)報。
3.1.2 ->receiveDatagram()
- 功能:接收一個UDP數(shù)據(jù)報。
- 返回值:
QNetworkDatagram對象,包含接收到的數(shù)據(jù)、發(fā)送方地址和端口。 - 說明:通常與
readyRead信號配合使用,在數(shù)據(jù)可讀時調(diào)用。
3.1.3 ->writeDatagram(const QNetworkDatagram &datagram)
- 功能:發(fā)送一個UDP數(shù)據(jù)報。
- 參數(shù):
QNetworkDatagram對象,包含要發(fā)送的數(shù)據(jù)、目標地址和端口。 - 返回值:發(fā)送的字節(jié)數(shù),若出錯返回-1。
3.1.4 ->readyRead信號
- 觸發(fā)時機:當socket接收到數(shù)據(jù)并準備好讀取時發(fā)出。
- 用途:通常連接到一個槽函數(shù),在該函數(shù)中調(diào)用
receiveDatagram()處理數(shù)據(jù)。
3.2 ->QNetworkDatagram類的主要方法
3.2.1 -> 構(gòu)造函數(shù)QNetworkDatagram(const QByteArray &data, const QHostAddress &address, quint16 port)
- 功能:構(gòu)造一個用于發(fā)送的數(shù)據(jù)報。
- 參數(shù):
data:要發(fā)送的數(shù)據(jù)。address:目標IP地址。port:目標端口。
3.2.2 ->data()
- 功能:獲取數(shù)據(jù)報中的數(shù)據(jù)內(nèi)容。
- 返回值:
QByteArray類型。
3.2.3 ->senderAddress()和senderPort()
- 功能:獲取發(fā)送該數(shù)據(jù)報的源IP地址和端口。
- 說明:適用于接收到的數(shù)據(jù)報,用于識別發(fā)送方。
3.2.4 ->destinationAddress()和destinationPort()
- 功能:獲取數(shù)據(jù)報的目標地址和端口。
- 說明:適用于發(fā)送或接收的數(shù)據(jù)報。
4 -> UDP Socket 工作流程簡述
創(chuàng)建與綁定:
- 創(chuàng)建
QUdpSocket對象。 - 調(diào)用
bind()綁定本地地址和端口。
- 創(chuàng)建
接收數(shù)據(jù):
- 連接
readyRead信號到自定義槽函數(shù)。 - 在槽函數(shù)中調(diào)用
receiveDatagram()獲取數(shù)據(jù)報。
- 連接
發(fā)送數(shù)據(jù):
- 構(gòu)造
QNetworkDatagram對象,填入數(shù)據(jù)、目標地址和端口。 - 調(diào)用
writeDatagram()發(fā)送。
- 構(gòu)造
錯誤處理:
- 可通過
error()和errorString()獲取錯誤信息。 - 建議在關(guān)鍵操作后檢查返回值。
- 可通過
5 -> 注意事項
- 數(shù)據(jù)報大小限制:UDP數(shù)據(jù)報大小通常不超過64KB(包括IP頭部),實際應用中建議控制在1500字節(jié)以內(nèi)以避免分片。
- 無序與丟包:UDP不保證數(shù)據(jù)順序和可靠性,需在應用層實現(xiàn)必要的確認、重傳或排序機制。
- 多播與廣播:
QUdpSocket支持多播和廣播,可通過joinMulticastGroup()等方法實現(xiàn)。 - 線程安全:Qt網(wǎng)絡類通常建議在同一線程中使用,跨線程訪問需謹慎處理。
6 -> 代碼示例
6.1 -> 回顯服務端
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QNetworkDatagram>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建對象
socket = new QUdpSocket(this);
// 設置窗口標題
this->setWindowTitle("服務器");
// 連接信號槽
connect(socket, &QUdpSocket::readyRead, this, &Widget::processRequest);
// 綁定端口號
bool ret = socket->bind(QHostAddress::Any, 9090);
if (!ret)
{
QMessageBox::critical(this, "服務器啟動出錯", socket->errorString());
return;
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::processRequest()
{
// 1. 讀取請求并解析
const QNetworkDatagram& requestDatagram = socket->receiveDatagram();
QString request = requestDatagram.data();
// 2. 根據(jù)請求計算響應. (由于是回顯服務器. 響應不需要計算, 就是請求本身)
const QString& response = process(request);
// 3. 把響應寫回給客戶端
QNetworkDatagram responseDatagram(response.toUtf8(), requestDatagram.senderAddress(), requestDatagram.senderPort());
socket->writeDatagram(responseDatagram);
// 把這次交互的信息, 顯示到界面上
QString log = "[" + requestDatagram.senderAddress().toString() + QString::number(requestDatagram.senderPort())
+ "]" + "req: " + request + "resp: " + response;
ui->listWidget->addItem(log);
}
QString Widget::process(const QString &request)
{
// 由于當前是回顯服務器, 響應就是和請求完全一樣
// 對于一個成熟的商業(yè)服務器, 這里請求->響應的計算過程可能是非常復雜的(業(yè)務邏輯)
return request;
}
6.2 -> 回顯客戶端
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QNetworkDatagram>
// 定義兩個常量, 描述服務器的 地址 和 端口
const QString& SERVER_IP = "127.0.0.1";
const quint16 SERVER_PORT = 9090;
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
socket = new QUdpSocket(this);
// 修改窗口標題
this->setWindowTitle("客戶端");
// 通過信號槽, 來處理服務器返回的數(shù)據(jù)
connect(socket, &QUdpSocket::readyRead, this, &Widget::processResponse);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
// 1. 獲取到輸入框的內(nèi)容
QString text = ui->lineEdit->text();
// 2. 構(gòu)造 UDP 的請求數(shù)據(jù)
QNetworkDatagram requestDatagram(text.toUtf8(), QHostAddress(SERVER_IP), SERVER_PORT);
// 3. 發(fā)送請求數(shù)據(jù)
socket->writeDatagram(requestDatagram);
// 4. 把發(fā)送的請求也添加到列表框中
ui->listWidget->addItem("客戶端說: " + text);
// 5. 清空輸入框
ui->lineEdit->setText("");
}
void Widget::processResponse()
{
// 通過這個函數(shù)來處理收到的響應.
// 1. 讀取到響應數(shù)據(jù)
const QNetworkDatagram responseDatagram = socket->receiveDatagram();
QString response = responseDatagram.data();
// 2. 把響應數(shù)據(jù)顯示到界面上
ui->listWidget->addItem("服務器說: " + response);
}

7 -> 總結(jié)
Qt 的 QUdpSocket 和 QNetworkDatagram 類為UDP網(wǎng)絡編程提供了簡潔而強大的封裝。通過它們,開發(fā)者可以快速實現(xiàn)基于UDP的通信功能,適用于實時性高、允許丟包的場景。盡管UDP本身不可靠,但結(jié)合適當?shù)膽脤訁f(xié)議設計,仍可構(gòu)建穩(wěn)定高效的網(wǎng)絡應用。
Qt Network模塊的跨平臺特性使得同一套代碼可在Windows、Linux、macOS等系統(tǒng)中運行,極大提升了開發(fā)效率。在實際項目中,若需更可靠的通信,可考慮使用TCP;若追求低延遲和高實時性,UDP則是更佳選擇。
到此這篇關(guān)于Qt UDP Socket的具體使用的文章就介紹到這了,更多相關(guān)Qt UDP Socket內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VSCode下.json文件的編寫之(1) linux/g++ (2).json中參數(shù)與預定義變量的意義解釋
這篇文章主要介紹了VSCode下.json文件的編寫之(1) linux/g++ (2).json中參數(shù)與預定義變量的意義解釋,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
C++ 將文件數(shù)據(jù)一次性加載進內(nèi)存實例代碼
這篇文章主要介紹了C++ 將文件數(shù)據(jù)一次性加載進內(nèi)存實例代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05
C++ 中類(class)和結(jié)構(gòu)體(struct)的區(qū)別
類和結(jié)構(gòu)體經(jīng)常被用來定義復雜的數(shù)據(jù)結(jié)構(gòu),但兩者之間既有區(qū)別又能很好地結(jié)合使用,本文主要介紹了C++ 中類(class)和結(jié)構(gòu)體(struct)的區(qū)別,具有一定的參考價值,感興趣的可以了解一下2025-04-04

