最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++?Qt開發(fā)之使用QUdpSocket實(shí)現(xiàn)UDP網(wǎng)絡(luò)通信

 更新時(shí)間:2024年03月19日 14:05:48   作者:lyshark  
Qt 是一個(gè)跨平臺(tái)C++圖形界面開發(fā)庫(kù),利用Qt可以快速開發(fā)跨平臺(tái)窗體應(yīng)用程序,本文主要介紹如何運(yùn)用QUdpSocket組件實(shí)現(xiàn)基于UDP的網(wǎng)絡(luò)通信功能,需要的可以參考下

Qt 是一個(gè)跨平臺(tái)C++圖形界面開發(fā)庫(kù),利用Qt可以快速開發(fā)跨平臺(tái)窗體應(yīng)用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實(shí)現(xiàn)圖形化開發(fā)極大的方便了開發(fā)效率,本章將重點(diǎn)介紹如何運(yùn)用QUdpSocket組件實(shí)現(xiàn)基于UDP的網(wǎng)絡(luò)通信功能。

QTcpSocket組件功能類似,QUdpSocket組件是 Qt 中用于實(shí)現(xiàn)用戶數(shù)據(jù)報(bào)協(xié)議(UDP,User Datagram Protocol)通信的類。UDP 是一種無連接的、不可靠的數(shù)據(jù)傳輸協(xié)議,它不保證數(shù)據(jù)包的順序和可靠性,但具有低延遲和簡(jiǎn)單的特點(diǎn)。

以下是 QUdpSocket 類的完整函數(shù)及其簡(jiǎn)要解釋:

函數(shù)描述
QUdpSocket(QObject *parent = nullptr)構(gòu)造函數(shù),創(chuàng)建一個(gè)新的 QUdpSocket 對(duì)象。
~QUdpSocket()析構(gòu)函數(shù),釋放 QUdpSocket 對(duì)象及其資源。
void bind(const QHostAddress &address, quint16 port, BindMode mode = DefaultForPlatform)將套接字綁定到指定的本地地址和端口。
void close()關(guān)閉套接字。
bool joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface = QNetworkInterface())加入多播組。
bool leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface = QNetworkInterface())離開多播組。
qint64 pendingDatagramSize() const返回下一個(gè)待讀取的數(shù)據(jù)報(bào)的大小。
qint64 readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)讀取數(shù)據(jù)報(bào)。
QByteArray readDatagram(qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)讀取數(shù)據(jù)報(bào),返回 QByteArray 對(duì)象。
qint64 writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)發(fā)送數(shù)據(jù)報(bào)。
qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &address, quint16 port)發(fā)送數(shù)據(jù)報(bào),接受 QByteArray 對(duì)象。
QAbstractSocket::SocketState state() const返回套接字的當(dāng)前狀態(tài)。
QAbstractSocket::SocketType socketType() const返回套接字的類型。
bool isValid() const如果套接字有效,則返回 true;否則返回 false。
int error() const返回套接字的當(dāng)前錯(cuò)誤代碼。
QHostAddress localAddress() const返回本地地址。
quint16 localPort() const返回本地端口。
int readBufferSize() const返回讀取緩沖區(qū)的大小。
void setReadBufferSize(int size)設(shè)置讀取緩沖區(qū)的大小。
QNetworkInterface multicastInterface() const返回多播組的網(wǎng)絡(luò)接口。
void setMulticastInterface(const QNetworkInterface &iface)設(shè)置多播組的網(wǎng)絡(luò)接口。
bool hasPendingDatagrams() const如果有待讀取的數(shù)據(jù)報(bào),則返回 true;否則返回 false。
bool isReadable() const如果套接字可讀,則返回 true;否則返回 false。
bool isWritable() const如果套接字可寫,則返回 true;否則返回 false。
bool setSocketDescriptor(int socketDescriptor, QUdpSocket::SocketState socketState = ConnectedState, QIODevice::OpenMode openMode = ReadWrite)設(shè)置套接字描述符。
int socketDescriptor() const返回套接字描述符。
bool waitForReadyRead(int msecs = 30000)等待套接字可讀取數(shù)據(jù)。
bool waitForBytesWritten(int msecs = 30000)等待套接字已寫入指定字節(jié)數(shù)的數(shù)據(jù)。
void ignoreSslErrors(const QList<QSslError> &errors)忽略 SSL 錯(cuò)誤。
void abort()強(qiáng)制關(guān)閉套接字。
QNetworkProxy proxy() const返回套接字的代理設(shè)置。
void setProxy(const QNetworkProxy &networkProxy)設(shè)置套接字的代理設(shè)置。
QString errorString() const返回套接字的錯(cuò)誤消息字符串。

這些函數(shù)提供了在 UDP 通信中使用 QUdpSocket 的各種功能,包括綁定、發(fā)送和接收數(shù)據(jù)報(bào)、設(shè)置和獲取套接字的狀態(tài)等。

1.初始化部分

在初始化部分我們首先通過new QUdpSocket來實(shí)現(xiàn)創(chuàng)建UDP對(duì)象,QUdpSocket 構(gòu)造函數(shù)的函數(shù)原型如下:

QUdpSocket::QUdpSocket(QObject * parent = nullptr)

如上構(gòu)造函數(shù)創(chuàng)建一個(gè)新的 QUdpSocket 對(duì)象。如果提供了 parent 參數(shù),則會(huì)將新創(chuàng)建的 QUdpSocket 對(duì)象添加到 parent 對(duì)象的子對(duì)象列表中,并且在 parent 對(duì)象被銷毀時(shí)自動(dòng)銷毀 QUdpSocket 對(duì)象。如果沒有提供 parent 參數(shù),則 QUdpSocket 對(duì)象將不會(huì)有父對(duì)象,并且需要手動(dòng)管理其生命周期。

初始化結(jié)束后,則下一步需要調(diào)用bind(),bind() 函數(shù)是 QUdpSocket 類的一個(gè)成員函數(shù),用于將套接字綁定到特定的本地地址和端口。它的函數(shù)原型如下:

void QUdpSocket::bind(const QHostAddress &address, quint16 port, BindMode mode = DefaultForPlatform)
  • address:要綁定的本地地址,通常是 QHostAddress::Any,表示綁定到所有可用的網(wǎng)絡(luò)接口。
  • port:要綁定的本地端口號(hào)。
  • mode:綁定模式,指定套接字的行為。默認(rèn)值是 DefaultForPlatform,表示使用平臺(tái)默認(rèn)的綁定模式。

該函數(shù)允許 QUdpSocket 在本地網(wǎng)絡(luò)接口上監(jiān)聽傳入的數(shù)據(jù)報(bào)。一旦調(diào)用了 bind() 函數(shù),QUdpSocket 就可以接收來自指定地址和端口的數(shù)據(jù)報(bào)。

在調(diào)用 bind() 函數(shù)之后,如果成功綁定了指定的地址和端口,套接字將處于 BoundState 狀態(tài)。如果出現(xiàn)錯(cuò)誤,可以通過檢查 error() 函數(shù)獲取錯(cuò)誤代碼,并通過 errorString() 函數(shù)獲取錯(cuò)誤消息。

接著我們通過connect()函數(shù)依次綁定套接字到stateChanged狀態(tài)改變信號(hào),以及readyRead()讀取信號(hào)上,這段初始化代碼如下所示;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    udpSocket=new QUdpSocket(this);

    // 生成隨機(jī)整數(shù) 包含2000 - 不包含65534
    int randomInt = QRandomGenerator::global()->bounded(2000, 65534);

    if(udpSocket->bind(randomInt))
    {
        this->setWindowTitle(this->windowTitle() + " | 地址: " + getLocalAddress() + " 綁定端口:" + QString::number(udpSocket->localPort()));
    }

    connect(udpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
    onSocketStateChange(udpSocket->state());
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
}

接著切換到讀取信號(hào)所對(duì)應(yīng)的槽函數(shù)上,onSocketReadyRead是我們自定義的一個(gè)槽,該槽函數(shù)功能如下所示;

// 讀取收到的數(shù)據(jù)報(bào)
void MainWindow::onSocketReadyRead()
{
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());

        QHostAddress peerAddr;
        quint16 peerPort;
        udpSocket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);
        QString str=datagram.data();

        QString peer="[消息來自 " + peerAddr.toString()+":"+QString::number(peerPort)+"] | ";

        ui->plainTextEdit->appendPlainText(peer+str);
    }
}

首先在代碼中調(diào)用pendingDatagramSize函數(shù),pendingDatagramSize() 是 QUdpSocket 類的一個(gè)成員函數(shù),用于獲取下一個(gè)待讀取的數(shù)據(jù)報(bào)的大小。它的函數(shù)原型如下:

qint64 QUdpSocket::pendingDatagramSize() const

該函數(shù)返回一個(gè) qint64 類型的值,表示下一個(gè)待讀取的數(shù)據(jù)報(bào)的大?。ㄒ宰止?jié)為單位)。如果沒有待讀取的數(shù)據(jù)報(bào),或者發(fā)生了錯(cuò)誤,該函數(shù)將返回 -1。

通常,可以在調(diào)用 readDatagram() 函數(shù)之前調(diào)用 pendingDatagramSize() 函數(shù)來獲取下一個(gè)待讀取的數(shù)據(jù)報(bào)的大小。這樣可以為數(shù)據(jù)緩沖區(qū)分配正確大小的空間,以確保完整地讀取數(shù)據(jù)報(bào)。

當(dāng)有了待讀取字節(jié)后,接著就可以直接通過調(diào)用readDatagram函數(shù)來從套接字中讀取數(shù)據(jù)報(bào),readDatagram() 是 QUdpSocket 類的一個(gè)成員函數(shù),它有幾個(gè)重載形式,其中最常用的是:

qint64 QUdpSocket::readDatagram(char * data, qint64 maxSize, QHostAddress * address = nullptr, quint16 * port = nullptr)

該函數(shù)用于讀取數(shù)據(jù)報(bào)并將其存儲(chǔ)到指定的緩沖區(qū) data 中,最多讀取 maxSize 個(gè)字節(jié)的數(shù)據(jù)??蛇x參數(shù) address 和 port 用于返回?cái)?shù)據(jù)報(bào)的源地址和端口號(hào)。如果不需要這些信息,可以將它們?cè)O(shè)置為 nullptr。

函數(shù)返回實(shí)際讀取的字節(jié)數(shù),如果發(fā)生錯(cuò)誤,返回 -1。要查看錯(cuò)誤信息,可以使用 error() 和 errorString() 函數(shù)。

另外,還有一個(gè)更簡(jiǎn)單的重載形式:

QByteArray QUdpSocket::readDatagram(qint64 maxSize, QHostAddress * address = nullptr, quint16 * port = nullptr)

這個(gè)重載函數(shù)直接返回一個(gè) QByteArray 對(duì)象,其中包含了讀取的數(shù)據(jù)報(bào)。

2.單播與廣播消息

單播(Unicast)和廣播(Broadcast)是網(wǎng)絡(luò)通信中常見的兩種數(shù)據(jù)傳輸方式,它們?cè)跀?shù)據(jù)包的傳輸范圍和目標(biāo)數(shù)量上有所不同。

單播(Unicast)

單播是一種一對(duì)一的通信方式,其中數(shù)據(jù)包從一個(gè)發(fā)送者傳輸?shù)揭粋€(gè)接收者。在單播通信中,數(shù)據(jù)包只發(fā)送到目標(biāo)主機(jī)的網(wǎng)絡(luò)接口,并且只有目標(biāo)主機(jī)能夠接收和處理這個(gè)數(shù)據(jù)包。

  • 一對(duì)一通信:每個(gè)數(shù)據(jù)包只有一個(gè)發(fā)送者和一個(gè)接收者。
  • 目標(biāo)明確:數(shù)據(jù)包只發(fā)送到特定的目標(biāo)主機(jī),其他主機(jī)不會(huì)接收到這個(gè)數(shù)據(jù)包。
  • 點(diǎn)到點(diǎn)通信:適用于直接通信的場(chǎng)景,如客戶端與服務(wù)器之間的通信。

當(dāng)按鈕發(fā)送消息被點(diǎn)擊后,則是一種單播模式,通常該模式需要得到目標(biāo)地址與端口號(hào),并通過調(diào)用writeDatagram來實(shí)現(xiàn)數(shù)據(jù)的發(fā)送,該函數(shù)通過傳入三個(gè)參數(shù),分別是發(fā)送字符串,目標(biāo)地址與目標(biāo)端口來實(shí)現(xiàn)一對(duì)一推送。

void MainWindow::on_pushButton_clicked()
{
    QHostAddress targetAddr(ui->lineEdit_addr->text());
    QString portString = ui->lineEdit_port->text();
    quint16 targetPort = portString.toUShort();

    QString msg=ui->lineEdit_msg->text();
    QByteArray str=msg.toUtf8();

    // 發(fā)送數(shù)據(jù)報(bào)
    udpSocket->writeDatagram(str,targetAddr,targetPort);
    ui->plainTextEdit->appendPlainText("[單播消息] | " + msg);
}

廣播(Broadcast)

廣播是一種一對(duì)多的通信方式,其中數(shù)據(jù)包從一個(gè)發(fā)送者傳輸?shù)酵痪W(wǎng)絡(luò)中的所有主機(jī)。在廣播通信中,數(shù)據(jù)包被發(fā)送到網(wǎng)絡(luò)中的所有主機(jī),并且所有的主機(jī)都能夠接收和處理這個(gè)數(shù)據(jù)包。

  • 一對(duì)多通信:每個(gè)數(shù)據(jù)包有一個(gè)發(fā)送者,但可以有多個(gè)接收者。
  • 目標(biāo)不明確:數(shù)據(jù)包被發(fā)送到網(wǎng)絡(luò)中的所有主機(jī),不需要知道接收者的具體地址。
  • 廣播域:在局域網(wǎng)中進(jìn)行廣播,只有在同一廣播域內(nèi)的主機(jī)才能接收到廣播消息。
  • 網(wǎng)絡(luò)負(fù)載:在大型網(wǎng)絡(luò)中使用廣播可能會(huì)產(chǎn)生大量的網(wǎng)絡(luò)流量,影響網(wǎng)絡(luò)性能。

當(dāng)按鈕廣播消息被點(diǎn)擊后,則同樣是調(diào)用writeDatagram函數(shù)與,唯一的區(qū)別在于第二個(gè)參數(shù)并未指定地址,而是使用了QHostAddress::Broadcast來代替,意味著只要端口是一致的則對(duì)所有的客戶推送消息,其他保持不變。

void MainWindow::on_pushButton_2_clicked()
{
    // 廣播地址
    QString portString = ui->lineEdit_port->text();
    quint16 targetPort = portString.toUShort();

    QString  msg=ui->lineEdit_msg->text();
    QByteArray str=msg.toUtf8();
    udpSocket->writeDatagram(str,QHostAddress::Broadcast,targetPort);

    ui->plainTextEdit->appendPlainText("[廣播消息] | " + msg);
}

讀者可自行運(yùn)行兩次客戶端,此時(shí)的端口將會(huì)隨機(jī)分配,當(dāng)指定對(duì)端端口后就可以向其發(fā)送數(shù)據(jù),如下圖所示;具體實(shí)現(xiàn)細(xì)節(jié),請(qǐng)參考文章附件。

以上就是C++ Qt開發(fā)之使用QUdpSocket實(shí)現(xiàn)UDP網(wǎng)絡(luò)通信的詳細(xì)內(nèi)容,更多關(guān)于Qt QUdpSocket UDP網(wǎng)絡(luò)通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++中帶空格字符串的輸入問題解決

    C++中帶空格字符串的輸入問題解決

    這篇文章主要給大家介紹了關(guān)于如何解決C++中帶空格字符串的輸入問題,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-04-04
  • C++11線程、互斥量以及條件變量示例詳解

    C++11線程、互斥量以及條件變量示例詳解

    這篇文章主要介紹了C++11線程、互斥量以及條件變量,C++11增加了線程以及線程相關(guān)的類,很方便地支持了并發(fā)編程,使得編寫多線程程序的可移植性得到了很大的提高,本文通過實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2023-03-03
  • C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法

    C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法

    C++ 標(biāo)準(zhǔn)庫(kù)沒有提供所謂的日期類型,C++ 繼承了C語(yǔ)言用于日期和時(shí)間操作的結(jié)構(gòu)和函數(shù),這篇文章主要給大家介紹了C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2021-12-12
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • C/C++ 中sizeof(''a'')對(duì)比詳細(xì)介紹

    C/C++ 中sizeof(''a'')對(duì)比詳細(xì)介紹

    這篇文章主要介紹了C/C++ 中sizeof('a')的值對(duì)比詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • C++高級(jí)數(shù)據(jù)結(jié)構(gòu)之二叉查找樹

    C++高級(jí)數(shù)據(jù)結(jié)構(gòu)之二叉查找樹

    這篇文章主要介紹了C++高級(jí)數(shù)據(jù)結(jié)構(gòu)之二叉查找樹,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • C++與QML進(jìn)行數(shù)據(jù)交互的常見方法總結(jié)

    C++與QML進(jìn)行數(shù)據(jù)交互的常見方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了C++與QML進(jìn)行數(shù)據(jù)交互的常見方法,文中 的示例代碼講解詳細(xì),具有一定的參考價(jià)值,有需要的小伙伴可以跟隨小編一起了解一下
    2023-10-10
  • typedef和#define的用法以及區(qū)別

    typedef和#define的用法以及區(qū)別

    以下是對(duì)C/C++語(yǔ)言中,typedef和#define的用法以及區(qū)別進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下
    2013-10-10
  • C語(yǔ)言深入淺出分析函數(shù)指針

    C語(yǔ)言深入淺出分析函數(shù)指針

    函數(shù)指針是一個(gè)指針變量,它可以存儲(chǔ)函數(shù)的地址,然后使用函數(shù)指針,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言進(jìn)階教程之函數(shù)指針的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • STL  priority_queue(優(yōu)先隊(duì)列)詳解

    STL priority_queue(優(yōu)先隊(duì)列)詳解

    這篇文章主要介紹了 STL priority_queue(優(yōu)先隊(duì)列)詳解的相關(guān)資料,需要的朋友可以參考下
    2016-10-10

最新評(píng)論

弥勒县| 安图县| 禹州市| 渭源县| 长乐市| 双城市| 浦北县| 汉源县| 阿鲁科尔沁旗| 镇安县| 拜城县| 中方县| 龙泉市| 丹寨县| 普陀区| 渝中区| 巴里| 保靖县| 库尔勒市| 奉贤区| 象州县| 正蓝旗| 禹城市| 白河县| 隆子县| 汤阴县| 万山特区| 沈丘县| 镇原县| 岐山县| 泸定县| 贵南县| 定安县| 婺源县| 曲阜市| 甘泉县| 沅江市| 丰城市| 五原县| 海丰县| 迁西县|