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

7 -> 總結(jié)
Qt 的 QUdpSocket 和 QNetworkDatagram 類為UDP網(wǎng)絡(luò)編程提供了簡潔而強(qiáng)大的封裝。通過它們,開發(fā)者可以快速實(shí)現(xiàn)基于UDP的通信功能,適用于實(shí)時(shí)性高、允許丟包的場景。盡管UDP本身不可靠,但結(jié)合適當(dāng)?shù)膽?yīng)用層協(xié)議設(shè)計(jì),仍可構(gòu)建穩(wěn)定高效的網(wǎng)絡(luò)應(yīng)用。
Qt Network模塊的跨平臺(tái)特性使得同一套代碼可在Windows、Linux、macOS等系統(tǒng)中運(yùn)行,極大提升了開發(fā)效率。在實(shí)際項(xiàng)目中,若需更可靠的通信,可考慮使用TCP;若追求低延遲和高實(shí)時(shí)性,UDP則是更佳選擇。
到此這篇關(guān)于Qt UDP Socket的具體使用的文章就介紹到這了,更多相關(guān)Qt UDP Socket內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(168.求Excel表列名稱)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(168.求Excel表列名稱),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
codeblocks 對‘cv::waitKey(int)’未定義的引用方式
今天小編就為大家分享一篇codeblocks 對‘cv::waitKey(int)’未定義的引用方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
VS2019實(shí)現(xiàn)C++的第一個(gè)MFC程序
本文主要介紹了VS2019實(shí)現(xiàn)C++的第一個(gè)MFC程序,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06
QT5實(shí)現(xiàn)簡單的TCP通信的實(shí)現(xiàn)
本文主要介紹了QT5實(shí)現(xiàn)簡單的TCP通信的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
opencv 做人臉識(shí)別 opencv 人臉匹配分析
opencv 人臉識(shí)別通過級聯(lián)分類器對特征的分級篩選來確定是否是人臉,每個(gè)節(jié)點(diǎn)的正確識(shí)別率很高,但正確拒絕率很低,任一節(jié)點(diǎn)判斷沒有人臉特征則結(jié)束運(yùn)算,宣布不是人臉2012-11-11

