Qt中QUdpSocket類的簡單使用詳解
QUdpSocket類的簡單使用
下面我們用一個(gè)做一個(gè)簡單的例子。
一、發(fā)送端
發(fā)送端界面:

發(fā)送端代碼:
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QUdpSocket>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_btnUnicast_clicked();
void on_btnBoardcast_clicked();
private:
Ui::MainWindow *ui;
QUdpSocket* m_pSender = nullptr;
};
#endif // MAINWINDOW_H.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QHostAddress>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pSender = new QUdpSocket(this);
}
MainWindow::~MainWindow()
{
delete ui;
delete m_pSender;
}
void MainWindow::on_btnUnicast_clicked()
{
QString strText = ui->lineEdit->text();
if(strText.isEmpty())
return;
QHostAddress host("127.0.0.1");
quint16 nPort = 8888;
qint64 nSend = m_pSender->writeDatagram(strText.toUtf8(),host,nPort);
if(nSend == -1)
{
qDebug() << "單播發(fā)送失敗" << m_pSender->errorString();
}
else
{
qDebug() << "單播發(fā)送成功,字節(jié)數(shù)" << nSend;
}
}
void MainWindow::on_btnBoardcast_clicked()
{
QString strText = ui->lineEdit->text();
if(strText.isEmpty())
return;
quint16 nPort = 8888;
qint64 nSend = m_pSender->writeDatagram(strText.toUtf8(),QHostAddress::Broadcast,nPort);
if(nSend == -1)
{
qDebug() << "廣播發(fā)送失敗" << m_pSender->errorString();
}
else
{
qDebug() << "廣播發(fā)送成功,字節(jié)數(shù)" << nSend;
}
}二、接收端
接受端的界面,比較簡單:

接受端代碼如下:
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QUdpSocket>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void ReadDatagram();
private:
Ui::MainWindow *ui;
QUdpSocket* m_pReceiver;
};
#endif // MAINWINDOW_H.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pReceiver = new QUdpSocket(this);
quint16 listenPort = 8888;
// 綁定端口:QHostAddress::Any 表示監(jiān)聽所有網(wǎng)卡的該端口(支持本機(jī)/局域網(wǎng)/外網(wǎng))
bool bBind = m_pReceiver->bind(QHostAddress::Any,listenPort);
if(!bBind)
{
ui->textEdit->append("綁定端口失敗:" + m_pReceiver->errorString());
}
else
{
ui->textEdit->append("已綁定端口 " + QString::number(listenPort) + ",等待接收數(shù)據(jù)...");
}
// 綁定接收數(shù)據(jù)信號:當(dāng)有數(shù)據(jù)到達(dá)時(shí)觸發(fā)readyRead()
connect(m_pReceiver,&QUdpSocket::readyRead,this,&MainWindow::ReadDatagram);
}
MainWindow::~MainWindow()
{
delete ui;
delete m_pReceiver;
}
void MainWindow::ReadDatagram()
{
// 循環(huán)讀取所有待處理的數(shù)據(jù)包(可能同時(shí)有多個(gè))
while (m_pReceiver->hasPendingDatagrams())
{
QByteArray datagram;
// 預(yù)留足夠的緩沖區(qū)(根據(jù)數(shù)據(jù)包大小調(diào)整,這里設(shè)為1024)
datagram.resize(m_pReceiver->pendingDatagramSize());
QHostAddress senderIp; // 發(fā)送方IP
quint16 senderPort; // 發(fā)送方端口
// 讀取數(shù)據(jù)包,同時(shí)獲取發(fā)送方的IP和端口
qint64 readBytes = m_pReceiver->readDatagram(
datagram.data(),
datagram.size(),
&senderIp,
&senderPort
);
if (readBytes == -1)
{
ui->textEdit->append("接收失?。? + m_pReceiver->errorString());
continue;
}
// 解析并顯示數(shù)據(jù)
QString recvData = QString::fromUtf8(datagram);
QString log = QString("[%1:%2] 接收數(shù)據(jù):%3")
.arg(senderIp.toString())
.arg(senderPort)
.arg(recvData);
ui->textEdit->append(log);
}
}代碼說明:
- 核心類
QUdpSocket:- 發(fā)送:
writeDatagram()直接發(fā)送數(shù)據(jù)包,無需建立連接,這是 UDP “無連接” 的核心體現(xiàn); - 接收:綁定端口后,通過
readyRead()信號監(jiān)聽數(shù)據(jù),readDatagram()讀取數(shù)據(jù)并獲取發(fā)送方信息; - 廣播:
QHostAddress::Broadcast是 UDP 獨(dú)有的能力,TCP 無法實(shí)現(xiàn)。
- 發(fā)送:
- 綁定端口的參數(shù):
QHostAddress::Any:監(jiān)聽所有網(wǎng)卡的指定端口,支持接收來自本機(jī)、局域網(wǎng)其他設(shè)備的 UDP 數(shù)據(jù);- 若僅監(jiān)聽本機(jī),可用
QHostAddress::LocalHost(127.0.0.1)。
- 數(shù)據(jù)編碼:
- 用
toUtf8()/fromUtf8()轉(zhuǎn)換QString和QByteArray,保證跨平臺編碼一致性,避免中文亂碼。
- 用
- 對比 TCP 的簡化點(diǎn):
- UDP 無需調(diào)用
connectToHost()建立連接,也無需處理connected()/disconnected()信號; - 無需處理粘包:
pendingDatagramSize()可獲取單個(gè)數(shù)據(jù)包的大小,一次讀取即可,而 TCP 需自定義協(xié)議拆包。
- UDP 無需調(diào)用
項(xiàng)目運(yùn)行結(jié)果:

到此這篇關(guān)于Qt中QUdpSocket類的簡單使用的文章就介紹到這了,更多相關(guān)Qt QUdpSocket類使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文搞懂C++中的四種強(qiáng)制類型轉(zhuǎn)換
很多朋友向小編了解C語言中怎么進(jìn)行強(qiáng)制類型轉(zhuǎn)換呢?在這小編告訴大家強(qiáng)制類型轉(zhuǎn)換可以分為兩種,一種是隱式類型轉(zhuǎn)換一種是顯示類型轉(zhuǎn)換,下面通過示例代碼給大家介紹下,需要的朋友參考下吧2021-07-07
C++代碼和可執(zhí)行程序在x86和arm上的區(qū)別介紹
這篇文章主要介紹了C++代碼和可執(zhí)行程序在x86和arm上的區(qū)別,X86和ARM是占據(jù)CPU市場的兩大處理器,各有優(yōu)劣,本文給大家詳細(xì)介紹了兩者的區(qū)別,需要的朋友可以參考下2022-07-07
C++ OpenCV實(shí)戰(zhàn)之標(biāo)記點(diǎn)檢測的實(shí)現(xiàn)
這篇文章主要介紹了如何利用C++ OpenCV實(shí)現(xiàn)關(guān)鍵點(diǎn)的檢測,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)OpenCV有一定幫助,感興趣的小伙伴可以了解一下2022-03-03
關(guān)于C++靜態(tài)成員函數(shù)訪問非靜態(tài)成員變量的問題
靜態(tài)成員函數(shù)不能訪問非靜態(tài)成員,這是因?yàn)殪o態(tài)函數(shù)屬于類而不是屬于整個(gè)對象,靜態(tài)函數(shù)中的 member可能都沒有分配內(nèi)存。靜態(tài)成員函數(shù)沒有隱含的this自變量。所以,它就無法訪問自己類的非靜態(tài)成員2013-10-10
Qt實(shí)現(xiàn)編輯數(shù)據(jù)庫數(shù)據(jù)的方法詳解
這篇文章主要為大家詳細(xì)介紹了Qt是如何實(shí)現(xiàn)編輯數(shù)據(jù)庫數(shù)據(jù)的,文中的示例代碼簡潔易懂,對我們深入了解QT有一定的幫助,感興趣的小伙伴可以了解一下2023-02-02

