0


【QT】UDP通信QUdpSocket(单播、广播、组播)

目录

1. UDP通信概述

UDP是无连接、不可靠、面向数据报(datagram)的协议,可以应用于对可靠性要求不高的场合。与TCP通信不同,UDP通信无需预先建立持久的socket连接,UDP每次发送数据报都需要指定目标地址和端口。

QUdpSocket以数据报传输数据,而不是以连续的数据流。发送数据报使用函数

QUdpSocket::writeDatagram()

,数据报的长度一般少于512字节,每个数据报包含发送者和接收者的IP地址和端口等信息。
UDP数据接收,首先要使用

QUdpSocket::bind()

绑定一个端口,绑定端口后,socket的状态会变为已绑定状态“BoundState”。当有数据报传入时,QudpSocket会自动发射

readyRead()

信号,在其槽函数中使用

QUdpSocket::readDatagram()

进行数据读取。

abort()

为解除绑定,解除后socket状态变为未连接状态“UnconnectedState”。

2. UDP消息传送的三种模式

单播模式(unicast):一个UDP客户端发送数据报到指定地址和端口的另一UDP客户端,是一对一的数据传输。

广播模式(broadcast):一个UDP客户端发出的数据报,在同一网络范围内其他所有的UDP客户端都可以收到。QUdpSocket支持IPv4广播。需要在数据报中指定接收端地址为

QHostAddress::Broadcast

,一般的广播地址是

255.255.255.255

组播模式(multicast):UDP客户端加入到另一个组播IP地址的多播组,成员向组播地址发送的数据报,其加入组播的所有成员都可以接收到,类似于QQ群功能。

QUdpSocket::joinMulticastGroup()

函数实现加入多播组的功能。

在单播、广播和多播模式下,UDP程序都是对等的,不像TCP通信分为客户端和服务端。
TCP通信只有单播模式。UDP通信虽然不能保证数据传输的准确性,但是具有灵活性,一般的即时通信软件都是基于UDP通信的。

3. QUdpSocket类的接口函数

bool bind(quint16 port = 0)

为UDP通信绑定一个端口

qint64 writeDatagram(QByteArray& datagram, QHostAddress& host, quint16 port)

向目标地址和端口的UDP客户端发送数据报,返回成功发送的字节数,数据报的长度一般不超过512字节。

bool hasPendingDatagrams()

当至少有一个数据报需要读取时,返回true

qint64 pendingDatagramSize()

返回第一个待读取的数据报的大小

qint64 readDatagram(char* data, qint64 maxSize)

读取一个数据报,返回成功读取的字节数

qint64 readDatagram(char* data, qint64 maxSize, QHostAddress* address, quint16* port)

读取一个数据报,返回成功读取的字节数。发送方的主机地址和端口存储在address和port中(除非指针为0)

bool joinMulticastGroup(QHostAddress& groupAddress)

加入一个多播组

bool leaveMulticastGroup(QHostAddress& groupAddress)

离开一个多播组

void abort()

终止当前连接并重置套接字。通常在析构函数中写入。与disconnectFromHost()不同,该函数立即关闭套接字,丢弃写入缓冲区中的任何挂起数据。

4. UDP单播和广播代码示例

4.1 测试说明

本实例实现UDP通信的单播和广播。两个实例可以运行在同一台计算机上,也可以运行在不同的计算机上。
这里的两个实例是运行在同一台计算机上,需要注意,在同一台计算机上运行时,两个实例需要绑定不同的端口。例如实例A绑定端口1600,实例B绑定端口3200,实例A向实例B发送数据报时,需要指定实例B的端口,这样实例B才能收到数据。
如果两个实例在不同的计算机上运行,则端口可以一样,因为IP地址不同了,不会导致绑定时发生冲突。一般的UDP通信程序都是在不同的计算机上运行的,约定一个固定的端口作为通信端口。

4.2 MainWindow.h

#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QAction>#include<QComboBox>#include<QGridLayout>#include<QHBoxLayout>#include<QHostInfo>#include<QLabel>#include<QLineEdit>#include<QMainWindow>#include<QMessageBox>#include<QPlainTextEdit>#include<QPushButton>#include<QSpinBox>#include<QUdpSocket>#include<QVBoxLayout>namespace Ui {classMainWindow;}classMainWindow:publicQMainWindow{
    Q_OBJECT

public:explicitMainWindow(QWidget* parent =0);~MainWindow();private slots:voidslotActBindPort();voidslotActUnbindPort();voidslotActClearText();voidslotActQuit();voidslotSocketStateChanged(QAbstractSocket::SocketState socketState);voidslotBtnSend();voidslotBtnBroad();voidslotSocketReadyRead();//读取socket传入的数据private:
    Ui::MainWindow* ui;

    QAction* m_pActBindPort;
    QAction* m_pActUnbindPort;
    QAction* m_pActClearText;
    QAction* m_pActQuit;
    QWidget* m_pCentralWidget;
    QLabel* m_pLabBindPort;
    QLabel* m_PLabTargetAddr;
    QLabel* m_pLabTargetPort;
    QSpinBox* m_pSpinBindPort;
    QComboBox* m_pComboTargetAddr;
    QSpinBox* m_pSpinTargetPort;
    QLineEdit* m_pLineEdit;
    QPushButton* m_pBtnSend;
    QPushButton* m_pBtnBroad;
    QPlainTextEdit* m_pPlainText;
    QLabel* m_pLabState;
    QUdpSocket* m_pUdpSocket;

    QString getLocalIP();};#endif// MAINWINDOW_H

4.3 MainWindow.cpp

#include"mainwindow.h"#include"ui_mainwindow.h"MainWindow::MainWindow(QWidget* parent):QMainWindow(parent),ui(new Ui::MainWindow){
    ui->setupUi(this);this->setWindowIcon(QIcon(":/new/prefix1/res/TitleIcon.png"));this->setWindowTitle(QStringLiteral("UDP Send/Receiver"));//工具栏
    ui->mainToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    m_pActBindPort =newQAction(QIcon(":/new/prefix1/res/绑定端口.png"),QStringLiteral("绑定端口"),this);
    m_pActUnbindPort =newQAction(QIcon(":/new/prefix1/res/解除绑定.png"),QStringLiteral("结束绑定"),this);
    m_pActClearText =newQAction(QIcon(":/new/prefix1/res/清空文本.png"),QStringLiteral("清空文本"),this);
    m_pActQuit =newQAction(QIcon(":/new/prefix1/res/退出.png"),QStringLiteral("退出"),this);
    ui->mainToolBar->addAction(m_pActBindPort);
    ui->mainToolBar->addAction(m_pActUnbindPort);
    ui->mainToolBar->addSeparator();
    ui->mainToolBar->addAction(m_pActClearText);
    ui->mainToolBar->addSeparator();
    ui->mainToolBar->addAction(m_pActQuit);//界面布局
    m_pCentralWidget =newQWidget(this);

    QHBoxLayout* HLay1 =new QHBoxLayout;
    m_pLabBindPort =newQLabel(QStringLiteral("绑定端口"), m_pCentralWidget);
    m_pSpinBindPort =newQSpinBox(m_pCentralWidget);
    m_pSpinBindPort->setMinimum(1);
    m_pSpinBindPort->setMaximum(65535);
    m_pSpinBindPort->setValue(1600);
    m_PLabTargetAddr =newQLabel(QStringLiteral("目标地址"), m_pCentralWidget);
    m_pComboTargetAddr =newQComboBox(m_pCentralWidget);
    m_pLabTargetPort =newQLabel(QStringLiteral("目标端口"), m_pCentralWidget);
    m_pSpinTargetPort =newQSpinBox(m_pCentralWidget);
    m_pSpinTargetPort->setMinimum(1);
    m_pSpinTargetPort->setMaximum(65535);
    m_pSpinTargetPort->setValue(3200);
    HLay1->addWidget(m_pLabBindPort,1, Qt::AlignRight);
    HLay1->addWidget(m_pSpinBindPort,2);
    HLay1->addWidget(m_PLabTargetAddr,1, Qt::AlignRight);
    HLay1->addWidget(m_pComboTargetAddr,4);
    HLay1->addWidget(m_pLabTargetPort,1, Qt::AlignRight);
    HLay1->addWidget(m_pSpinTargetPort,2);

    QHBoxLayout* HLay2 =new QHBoxLayout;
    m_pLineEdit =newQLineEdit(m_pCentralWidget);
    m_pBtnSend =newQPushButton(QStringLiteral("发送消息"), m_pCentralWidget);
    m_pBtnBroad =newQPushButton(QStringLiteral("广播消息"), m_pCentralWidget);
    HLay2->addWidget(m_pLineEdit);
    HLay2->addWidget(m_pBtnSend);
    HLay2->addWidget(m_pBtnBroad);

    QVBoxLayout* VLay =newQVBoxLayout(m_pCentralWidget);//主布局必须设置parent,否则不会显示布局// QVBoxLayout* VLay = new QVBoxLayout();
    VLay->addLayout(HLay1);
    VLay->addLayout(HLay2);
    m_pPlainText =newQPlainTextEdit(m_pCentralWidget);
    VLay->addWidget(m_pPlainText);this->setCentralWidget(m_pCentralWidget);this->setLayout(VLay);//设置为窗体的主布。在指定了主布局的parent之后,这句话可有可无

    QString localIP =getLocalIP();this->setWindowTitle(this->windowTitle()+"---IP:"+ localIP);
    m_pComboTargetAddr->addItem(localIP);
    m_pUdpSocket =newQUdpSocket(this);//状态栏
    m_pLabState =newQLabel(QStringLiteral("socket状态:"),this);
    m_pLabState->setMinimumWidth(150);
    ui->statusBar->addWidget(m_pLabState);// connectconnect(m_pActBindPort,&QAction::triggered,this,&MainWindow::slotActBindPort);connect(m_pActUnbindPort,&QAction::triggered,this,&MainWindow::slotActUnbindPort);connect(m_pActClearText,&QAction::triggered,this,&MainWindow::slotActClearText);connect(m_pActQuit,&QAction::triggered,this,&MainWindow::slotActQuit);connect(m_pBtnSend,&QPushButton::clicked,this,&MainWindow::slotBtnSend);connect(m_pBtnBroad,&QPushButton::clicked,this,&MainWindow::slotBtnBroad);connect(m_pUdpSocket,&QUdpSocket::stateChanged,this,&MainWindow::slotSocketStateChanged);connect(m_pUdpSocket,&QUdpSocket::readyRead,this,&MainWindow::slotSocketReadyRead);}MainWindow::~MainWindow(){
    m_pUdpSocket->abort();delete m_pUdpSocket;
    m_pUdpSocket =nullptr;delete ui;}voidMainWindow::slotActBindPort(){
    quint16 port = m_pSpinBindPort->value();//本机UDP端口if(m_pUdpSocket->bind(port)){
        m_pPlainText->appendPlainText("**已成功绑定");
        m_pPlainText->appendPlainText("绑定端口:"+QString::number(m_pUdpSocket->localPort()));//使能
        m_pActBindPort->setEnabled(false);
        m_pActUnbindPort->setEnabled(true);}else{
        m_pPlainText->appendPlainText("绑定失败");}}voidMainWindow::slotActUnbindPort(){
    m_pUdpSocket->abort();//解除绑定
    m_pPlainText->appendPlainText("**已解除绑定");

    m_pActBindPort->setEnabled(true);
    m_pActUnbindPort->setEnabled(false);}voidMainWindow::slotActClearText(){ m_pPlainText->clear();}voidMainWindow::slotActQuit(){
    QMessageBox::StandardButton button =QMessageBox::question(this,"","是否要退出?");if(button == QMessageBox::StandardButton::Yes)this->close();}voidMainWindow::slotSocketStateChanged(QAbstractSocket::SocketState socketState){switch(socketState){case QAbstractSocket::UnconnectedState: m_pLabState->setText("socket状态:UnconnectedState");break;case QAbstractSocket::HostLookupState: m_pLabState->setText("socket状态:HostLookupState");break;case QAbstractSocket::ConnectingState: m_pLabState->setText("socket状态:ConnectingState");break;case QAbstractSocket::ConnectedState: m_pLabState->setText("socket状态:ConnectedState");break;case QAbstractSocket::BoundState: m_pLabState->setText("socket状态:BoundState");break;case QAbstractSocket::ClosingState: m_pLabState->setText("socket状态:ClosingState");break;default:break;}}voidMainWindow::slotBtnSend(){
    QString msg = m_pLineEdit->text();
    QByteArray str = msg.toUtf8();
    QString targetIp = m_pComboTargetAddr->currentText();//目标IP
    QHostAddress targetAddr(targetIp);
    quint16 targetPort = m_pSpinTargetPort->value();//目标端口
    m_pUdpSocket->writeDatagram(str, targetAddr, targetPort);
    m_pPlainText->appendPlainText("[out] "+ msg);
    m_pLineEdit->clear();
    m_pLineEdit->setFocus();}voidMainWindow::slotBtnBroad(){
    QString msg = m_pLineEdit->text();
    QByteArray str = msg.toUtf8();
    quint16 targetPort = m_pSpinTargetPort->value();
    m_pUdpSocket->writeDatagram(str, QHostAddress::Broadcast, targetPort);
    m_pPlainText->appendPlainText("[out] "+ msg);
    m_pLineEdit->clear();
    m_pLineEdit->setFocus();}voidMainWindow::slotSocketReadyRead(){while(m_pUdpSocket->hasPendingDatagrams()){
        QByteArray dataGram;
        dataGram.resize(m_pUdpSocket->pendingDatagramSize());
        QHostAddress peerAddress;
        quint16 peerPort;
        m_pUdpSocket->readDatagram(dataGram.data(), dataGram.size(),&peerAddress,&peerPort);
        QString str = dataGram.data();
        QString peer ="[From "+ peerAddress.toString()+":"+QString::number(peerPort)+"]";
        m_pPlainText->appendPlainText(peer + str);}}

QString MainWindow::getLocalIP(){
    QString hostName =QHostInfo::localHostName();
    QHostInfo hostInfo =QHostInfo::fromName(hostName);
    QString localIP ="";
    QList<QHostAddress> addrList = hostInfo.addresses();if(!addrList.isEmpty()){for(int i =0; i < addrList.size(); i++){
            QHostAddress addr = addrList.at(i);if(QAbstractSocket::IPv4Protocol == addr.protocol()){
                localIP = addr.toString();break;}}}return localIP;}

4.4 界面展示

在这里插入图片描述

5. UDP组播代码示例

5.1 组播的特性

组播报文的目的地址使用D类IP地址,关于组播IP地址,有以下约定:

  1. 224.0.0.0 ~ 224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其他地址供路由协议使用。
  2. 224.0.1.0 ~ 224.0.1.255是公用组播地址,可以用于Internet。
  3. 224.0.2.0 ~ 238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效。
  4. 239.0.0.0 ~ 239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。所以,若是在家庭或办公室局域网内测试UDP组播功能,可以使用这些IP。

5.2 MainWindow.h

#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QAction>#include<QComboBox>#include<QHBoxLayout>#include<QHostInfo>#include<QLabel>#include<QLineEdit>#include<QMainWindow>#include<QMessageBox>#include<QPlainTextEdit>#include<QPushButton>#include<QRegExp>#include<QSpinBox>#include<QUdpSocket>#include<QVBoxLayout>namespace Ui {classMainWindow;}classMainWindow:publicQMainWindow{
    Q_OBJECT

public:explicitMainWindow(QWidget* parent =0);~MainWindow();private slots:voidslotActJoinMulti();voidslotActLeaveMulti();voidslotActClearText();voidslotActQuit();voidslotSocketStateChanged(QAbstractSocket::SocketState socketState);voidslotBtnMultiMsg();voidslotReadyRead();private:
    Ui::MainWindow* ui;

    QAction* m_pActJoinMulti;
    QAction* m_pActLeaveMulti;
    QAction* m_pActClearText;
    QAction* m_pActQuit;
    QWidget* m_pCentralWidget;
    QLabel* m_pLabPort;
    QLabel* m_pLabAddr;
    QSpinBox* m_pSpinPort;
    QComboBox* m_pComboAddr;
    QLineEdit* m_pLineEdit;
    QPushButton* m_pBtnSendMulti;
    QPlainTextEdit* m_pPlainText;
    QLabel* m_pLabState;
    QUdpSocket* m_pUdpSocket;
    QHostAddress m_multicastAddr;

    QString getLocalIP();};#endif// MAINWINDOW_H

5.3 MainWindow.cpp

#include"mainwindow.h"#include"ui_mainwindow.h"MainWindow::MainWindow(QWidget* parent):QMainWindow(parent),ui(new Ui::MainWindow){
    ui->setupUi(this);this->setWindowTitle(QStringLiteral("UDP Multicast"));//工具栏
    ui->mainToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    m_pActJoinMulti =newQAction(QIcon(":/new/prefix1/res/添加群组.png"),QStringLiteral("加入组播"),this);
    m_pActLeaveMulti =newQAction(QIcon(":/new/prefix1/res/退出群组.png"),QStringLiteral("退出组播"),this);
    m_pActClearText =newQAction(QIcon(":/new/prefix1/res/清空.png"),QStringLiteral("清空文本"),this);
    m_pActQuit =newQAction(QIcon(":/new/prefix1/res/退出.png"),QStringLiteral("退出"),this);
    ui->mainToolBar->addAction(m_pActJoinMulti);
    ui->mainToolBar->addAction(m_pActLeaveMulti);
    ui->mainToolBar->addSeparator();
    ui->mainToolBar->addAction(m_pActClearText);
    ui->mainToolBar->addSeparator();
    ui->mainToolBar->addAction(m_pActQuit);//界面布局
    m_pCentralWidget =newQWidget(this);
    m_pLabPort =newQLabel(QStringLiteral("组播端口"), m_pCentralWidget);
    m_pSpinPort =newQSpinBox(m_pCentralWidget);
    m_pSpinPort->setMinimum(1);
    m_pSpinPort->setMaximum(65535);
    m_pSpinPort->setValue(3200);
    m_pLabAddr =newQLabel(QStringLiteral("组播地址"), m_pCentralWidget);
    m_pComboAddr =newQComboBox(m_pCentralWidget);
    m_pComboAddr->setEditable(true);//下拉框可编辑输入
    m_pComboAddr->addItem("239.0.0.1");// 正则匹配 D类IP:224.0.0.0~239.255.255.255// .必须使用转义字符\,否则.会匹配任意字符// C++中"\"在字符串中表示要用"\\"// 是 - 不是 ~ ; 是[0-9]不是[0~9]
    QRegExp regExp("^(22[4-9]|23[0-9])(\\.((\\d)|([1-9]\\d)|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))){3}$");
    QValidator* pValidator =newQRegExpValidator(regExp,this);
    m_pComboAddr->setValidator(pValidator);
    QHBoxLayout* HLay1 =newQHBoxLayout();
    HLay1->addWidget(m_pLabPort,1, Qt::AlignRight);
    HLay1->addWidget(m_pSpinPort,1);
    HLay1->addWidget(m_pLabAddr,1, Qt::AlignRight);
    HLay1->addWidget(m_pComboAddr,2);
    m_pLineEdit =newQLineEdit(m_pCentralWidget);
    m_pBtnSendMulti =newQPushButton(QStringLiteral("组播消息"), m_pCentralWidget);
    QHBoxLayout* HLay2 =newQHBoxLayout();
    HLay2->addWidget(m_pLineEdit,4);
    HLay2->addWidget(m_pBtnSendMulti,1);
    m_pPlainText =newQPlainTextEdit(m_pCentralWidget);
    QVBoxLayout* VLay =newQVBoxLayout(m_pCentralWidget);
    VLay->addLayout(HLay1);
    VLay->addLayout(HLay2);
    VLay->addWidget(m_pPlainText);this->setCentralWidget(m_pCentralWidget);this->setLayout(VLay);//状态栏
    m_pLabState =newQLabel(QStringLiteral("socket状态:"),this);
    m_pLabState->setMinimumWidth(150);
    ui->statusBar->addWidget(m_pLabState);

    QString str =getLocalIP();this->setWindowTitle(this->windowTitle()+"---IP:"+ str);

    m_pUdpSocket =newQUdpSocket(this);
    m_pUdpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);// connectconnect(m_pActJoinMulti,&QAction::triggered,this,&MainWindow::slotActJoinMulti);connect(m_pActLeaveMulti,&QAction::triggered,this,&MainWindow::slotActLeaveMulti);connect(m_pActClearText,&QAction::triggered,this,&MainWindow::slotActClearText);connect(m_pActQuit,&QAction::triggered,this,&MainWindow::slotActQuit);connect(m_pUdpSocket,&QUdpSocket::stateChanged,this,&MainWindow::slotSocketStateChanged);connect(m_pBtnSendMulti,&QPushButton::clicked,this,&MainWindow::slotBtnMultiMsg);connect(m_pUdpSocket,&QUdpSocket::readyRead,this,&MainWindow::slotReadyRead);}MainWindow::~MainWindow(){delete ui;}voidMainWindow::slotActJoinMulti(){
    QString ip = m_pComboAddr->currentText();
    m_multicastAddr =QHostAddress(ip);
    quint16 multicastPort = m_pSpinPort->value();if(m_pUdpSocket->bind(QHostAddress::AnyIPv4, multicastPort, QUdpSocket::ShareAddress)){
        m_pUdpSocket->joinMulticastGroup(m_multicastAddr);//加入多播组
        m_pPlainText->appendPlainText("**加入组播成功");
        m_pPlainText->appendPlainText("**组播地址IP:"+ ip);
        m_pPlainText->appendPlainText("**绑定端口:"+QString::number(multicastPort));
        m_pActJoinMulti->setEnabled(false);
        m_pActLeaveMulti->setEnabled(true);
        m_pComboAddr->setEditable(false);}else{
        m_pPlainText->appendPlainText("**绑定端口失败");}}voidMainWindow::slotActLeaveMulti(){
    m_pUdpSocket->leaveMulticastGroup(m_multicastAddr);//退出组播
    m_pUdpSocket->abort();//解除绑定
    m_pActJoinMulti->setEnabled(true);
    m_pActLeaveMulti->setEnabled(false);
    m_pComboAddr->setEnabled(true);
    m_pComboAddr->setEditable(true);
    m_pPlainText->appendPlainText("**已退出组播,解除端口绑定");}voidMainWindow::slotActClearText(){ m_pPlainText->clear();}voidMainWindow::slotActQuit(){
    QMessageBox::StandardButton button =QMessageBox::question(this,"","是否退出?");if(QMessageBox::StandardButton::Yes == button){this->close();}}voidMainWindow::slotSocketStateChanged(QAbstractSocket::SocketState socketState){// case并不包含所有的情况,因为没有写listening的情况,所以就需要写defaultswitch(socketState){case QAbstractSocket::UnconnectedState: m_pLabState->setText("socket状态:UnconnectedState");break;case QAbstractSocket::HostLookupState: m_pLabState->setText("socket状态:HostLookupState");break;case QAbstractSocket::ConnectingState: m_pLabState->setText("socket状态:ConnectingState");break;case QAbstractSocket::ConnectedState: m_pLabState->setText("socket状态:ConnectedState");break;case QAbstractSocket::BoundState: m_pLabState->setText("socket状态:BoundState");break;case QAbstractSocket::ClosingState: m_pLabState->setText("socket状态:ClosingState");break;default:break;}}voidMainWindow::slotBtnMultiMsg(){
    QString msg = m_pLineEdit->text();
    QByteArray str = msg.toUtf8();
    quint16 multiPort = m_pSpinPort->value();
    m_pUdpSocket->writeDatagram(str, m_multicastAddr, multiPort);
    m_pPlainText->appendPlainText("[multicast] "+ msg);
    m_pLineEdit->clear();
    m_pLineEdit->setFocus();}voidMainWindow::slotReadyRead(){while(m_pUdpSocket->hasPendingDatagrams()){
        QByteArray dataGram;
        dataGram.resize(m_pUdpSocket->pendingDatagramSize());
        QHostAddress peerAddr;
        quint16 peerPort;
        m_pUdpSocket->readDatagram(dataGram.data(), dataGram.size(),&peerAddr,&peerPort);
        QString str = dataGram.data();
        QString peer ="[From "+ peerAddr.toString()+":"+QString::number(peerPort)+"] ";
        m_pPlainText->appendPlainText(peer + str);qDebug()<< m_pUdpSocket->peerAddress();qDebug()<< m_pUdpSocket->localAddress().toString();qDebug()<< m_pUdpSocket->localPort();}}

QString MainWindow::getLocalIP(){
    QString localName =QHostInfo::localHostName();
    QHostInfo hostInfo =QHostInfo::fromName(localName);
    QList<QHostAddress> addrList = hostInfo.addresses();
    QString localIP ="";if(!addrList.isEmpty()){for(int i =0; i < addrList.size(); i++){
            QHostAddress addr = addrList.at(i);if(QAbstractSocket::IPv4Protocol == addr.protocol()){
                localIP = addr.toString();break;}}}return localIP;}

5.4 界面展示

在这里插入图片描述

标签: udp qt 网络

本文转载自: https://blog.csdn.net/WL0616/article/details/129050373
版权归原作者 半醒半醉日复日,花落花开年复年 所有, 如有侵权,请联系我们删除。

“【QT】UDP通信QUdpSocket(单播、广播、组播)”的评论:

还没有评论