网站制作标准,wordpress托管 根目录,丹徒网站建设包括哪些,网站设计方案书ppt1. UDP通信概述 UDP是无连接、不可靠、面向数据报#xff08;datagram#xff09;的协议#xff0c;可以应用于对可靠性要求不高的场合。与TCP通信不同#xff0c;UDP通信无需预先建立持久的socket连接#xff0c;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。
组播模式multicastUDP客户端加入到另一个组播IP地址的多播组成员向组播地址发送的数据报其加入组播的所有成员都可以接收到类似于QQ群功能。QUdpSocket::joinMulticastGroup()函数实现加入多播组的功能。
QUdpSocket::leaveMulticastGroup()函数实现
在单播、广播和多播模式下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()不同该函数立即关闭套接字丢弃写入缓冲区中的任何挂起数据。 原文链接https://blog.csdn.net/WL0616/article/details/129050373
4.UDP对话小案例
实现发送和接收端互相发信息类似QQ (界面使用UI设计)
4.1.接收端
receiver.h
#ifndef RECESIVER_H
#define RECESIVER_H#include QWidget
#include QUdpSocket
QT_BEGIN_NAMESPACE
namespace Ui { class Recesiver; }
QT_END_NAMESPACEclass Recesiver : public QWidget
{Q_OBJECTpublic:Recesiver(QWidget *parent nullptr);~Recesiver();private slots:void on_pushButton_2_clicked(); //启动槽函数void start();void on_pushButton_clicked();private:Ui::Recesiver *ui;QUdpSocket *receiver;
};
#endif // RECESIVER_Hreceiver.cpp
#include recesiver.h
#include ui_recesiver.hRecesiver::Recesiver(QWidget *parent): QWidget(parent), ui(new Ui::Recesiver)
{ui-setupUi(this);setWindowTitle(QStringLiteral(接收端));ui-lineEdit-setText(127.0.0.1);receiver new QUdpSocket(this);
}Recesiver::~Recesiver()
{delete ui;
}//接收信息void Recesiver::start(){QByteArray datagram;datagram.resize(receiver-pendingDatagramSize()); //接收到的数据的长度receiver-readDatagram(datagram.data(),datagram.size());ui-textEdit-append(QStringLiteral(对方)datagram);}//启动按钮发送端发送信息给接收端
void Recesiver::on_pushButton_2_clicked()
{receiver-bind(ui-lineEdit_2-text().toInt());//设置端口号将其转为整型connect(receiver,QUdpSocket::readyRead,this,[](){start();});ui-pushButton_2-setEnabled(false);ui-lineEdit_2-setEnabled(false);
}//发送按钮接收端发送信息给发送端
void Recesiver::on_pushButton_clicked()
{QByteArray datagramui-textEdit_2-toPlainText().toUtf8(); //在输入端输入发送的内容receiver-writeDatagram(datagram.data(),datagram.size(),QHostAddress(ui-lineEdit-text()),ui-lineEdit_3-text().toInt());//qint64 writeDatagram(const char *data, qint64 len, const QHostAddress host, quint16 port);//发送数据大小发送主机的ip,发送主机的端口号ui-textEdit-append(QStringLiteral(本机)ui-textEdit_2-toPlainText());//发送信息的具体内容在发送端的聊天记录里能体现ui-textEdit_2-clear();
}4.2发送端
sender.h
#ifndef SENDER_H
#define SENDER_H
#include QWidget
#include QUdpSocket
QT_BEGIN_NAMESPACE
namespace Ui { class Sender; }
QT_END_NAMESPACEclass Sender : public QWidget
{Q_OBJECTpublic:Sender(QWidget *parent nullptr);~Sender();void start2();
private slots:void on_pushButton_clicked();private:Ui::Sender *ui;QUdpSocket *sender;
};
#endif // SENDER_Hsender.cpp
#include sender.h
#include ui_sender.hSender::Sender(QWidget *parent): QWidget(parent), ui(new Ui::Sender)
{ui-setupUi(this);sendernew QUdpSocket(this);setWindowTitle(QStringLiteral(发送端));//senderui-lineEdit_3-setText(888);sender-bind(ui-lineEdit_3-text().toInt());//绑定端口号connect(sender,QUdpSocket::readyRead,this,[](){start2();});//start2();
}void Sender::start2()
{QByteArray datagram;datagram.resize(sender-pendingDatagramSize()); //接收到的数据的长度sender-readDatagram(datagram.data(),datagram.size());ui-textEdit-append(QStringLiteral(对方)datagram);
}Sender::~Sender()
{delete ui;
}//发送按钮 发送信息给接收端
void Sender::on_pushButton_clicked()
{QByteArray datagramui-textEdit_2-toPlainText().toUtf8(); //在输入端输入发送的内容sender-writeDatagram(datagram.data(),datagram.size(),QHostAddress(ui-lineEdit-text()),ui-lineEdit_2-text().toInt());//qint64 writeDatagram(const char *data, qint64 len, const QHostAddress host, quint16 port);//发送数据大小发送主机的ip,发送主机的端口号ui-textEdit-append(QStringLiteral(本机)ui-textEdit_2-toPlainText());//发送信息的具体内容在发送端的聊天记录里能体现ui-textEdit_2-clear();}结果
ps对话有点搞笑哈哈哈 5.4. UDP单播和广播代码示例
4.1 测试说明 本实例实现UDP通信的单播和广播。两个实例可以运行在同一台计算机上也可以运行在不同的计算机上。 这里的两个实例是运行在同一台计算机上需要注意在同一台计算机上运行时两个实例需要绑定不同的端口。例如实例A绑定端口1600实例B绑定端口3200实例A向实例B发送数据报时需要指定实例B的端口这样实例B才能收到数据。 如果两个实例在不同的计算机上运行则端口可以一样因为IP地址不同了不会导致绑定时发生冲突。一般的UDP通信程序都是在不同的计算机上运行的约定一个固定的端口作为通信端口。
4.2主要程序
用UI设计器件和代码化UI分别设计
ui设计器设计
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include QMainWindow
#include QLabel
#include QAbstractSocket
#include QUdpSocket
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow();void handleEvents(); // 信号与槽处理private:Ui::MainWindow *ui;QUdpSocket *udpScoket;QLabel *labstateScoket; //Scoket状态栏标签QString getLocalIp(); //获取本机的IP地址
private slots:void slotActBindPort(); //绑定端口void slotActUnbindPort(); //解除端口void slotActClearText(); //清空文本框void slotActQuit(); //退出void slotSocketReadyRead(); //读取socket传入的数据void slotSocketStateChanged(QAbstractSocket::SocketState socketState);void on_pushButton_clicked(); //发送信息void on_pushButton_2_clicked(); //广播信息
};
#endif // MAINWINDOW_H.cpp
#include mainwindow.h
#include ui_mainwindow.h
#include QTextEdit
#include QMessageBox
#include QHostInfo#include QAction
#include QPushButton
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui-setupUi(this);QString localIP getLocalIp(); //获取本机的IP地址this-setWindowTitle(this-windowTitle() ---IP: localIP);ui-comboBox-addItem(localIP); //在目标地址中添加IPudpScoket new QUdpSocket(this);//状态栏labstateScoket new QLabel(QStringLiteral(socket状态), this);labstateScoket-setMinimumWidth(150);ui-statusBar-addWidget(labstateScoket);handleEvents();ui-spinBox-setMinimum(1); //设置绑定端口的最大最小值和当前的端口值ui-spinBox-setMaximum(65535);ui-spinBox-setValue(1600);ui-spinBox_2-setMinimum(1); //设置目标端口的最大最小值和当前的端口值ui-spinBox_2-setMaximum(65535);ui-spinBox_2-setValue(3200);}MainWindow::~MainWindow()
{udpScoket-abort();delete udpScoket;udpScoket nullptr;delete ui;
}// 信号与槽处理
void MainWindow::handleEvents()
{connect(ui-action, QAction::triggered, this, MainWindow::slotActBindPort );connect(ui-action_2, QAction::triggered, this, MainWindow::slotActUnbindPort);connect(ui-action_3, QAction::triggered, this, MainWindow::slotActClearText);connect(ui-action_4, QAction::triggered, this, MainWindow::slotActQuit);connect(ui-pushButton, QPushButton::clicked, this, MainWindow::on_pushButton_clicked);connect(ui-pushButton_2, QPushButton::clicked, this, MainWindow::on_pushButton_2_clicked);connect(udpScoket, QUdpSocket::stateChanged, this, MainWindow::slotSocketStateChanged);connect(udpScoket, QUdpSocket::readyRead, this, MainWindow::slotSocketReadyRead);}QString MainWindow::getLocalIp()
{QString hostName QHostInfo::localHostName();//获取本机主机名QHostInfo hostInfo QHostInfo::fromName(hostName); //返回主机名的IP地址QString localIP ;QListQHostAddress addrList hostInfo.addresses(); //主机IP地址列表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;
}//绑定端口
void MainWindow::slotActBindPort()
{quint16 portui-spinBox-value(); //绑定本机UDp端口if(udpScoket-bind(port)){ui-textEdit-append(QStringLiteral(**已经绑定成功));ui-textEdit-append(QStringLiteral(**绑定端口)QString::number(udpScoket-localPort()));ui-action-setEnabled(false); //开始绑定失效ui-action_2-setEnabled(true);//解除绑定使能}elseui-textEdit-append(QStringLiteral(绑定失败));
}//解除端口
void MainWindow::slotActUnbindPort()
{udpScoket-abort();//解除绑定ui-action-setEnabled(true); //开始绑定失效ui-action_2-setEnabled(false);//解除绑定使能ui-textEdit-append(QStringLiteral(**已经解除绑定));}//清空文本框
void MainWindow::slotActClearText()
{ui-textEdit-clear();
}//退出
void MainWindow::slotActQuit()
{QMessageBox::StandardButton button QMessageBox::question(this, , QStringLiteral(是否要退出));if (button QMessageBox::StandardButton::Yes)this-close();
}//读取socket传入的数据
void MainWindow::slotSocketReadyRead()
{while(udpScoket-hasPendingDatagrams()) //当有数据传入数据报{QByteArray datagtam;datagtam.resize(udpScoket-pendingDatagramSize());//读取数据报大小QHostAddress peerAddr; //在已连接的状态下返回对方的socket的地址quint16 peerPort; //在已连接的状态下返回对方的socket的端口udpScoket-readDatagram(datagtam.data(),datagtam.size(),peerAddr,peerPort);//读取数据报的内容//qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host nullptr, quint16 *port nullptr);QString strdatagtam.data();QString peer[From peerAddr.toString():QString::number(peerPort)];ui-textEdit-append( peer str);}
}//状态栏显示Socket变化情况
void MainWindow::slotSocketStateChanged(QAbstractSocket::SocketState socketState)
{switch (socketState){case QAbstractSocket::UnconnectedState: labstateScoket-setText(QStringLiteral(socket状态UnconnectedState)); break;case QAbstractSocket::HostLookupState: labstateScoket-setText(QStringLiteral(socket状态HostLookupState)); break;case QAbstractSocket::ConnectingState: labstateScoket-setText(QStringLiteral(socket状态ConnectingState)); break;case QAbstractSocket::ConnectedState: labstateScoket-setText(QStringLiteral(socket状态ConnectedState)); break;case QAbstractSocket::BoundState: labstateScoket-setText(QStringLiteral(socket状态BoundState)); break;case QAbstractSocket::ClosingState: labstateScoket-setText(QStringLiteral(socket状态ClosingState)); break;default: break;}}//发送信息
void MainWindow::on_pushButton_clicked()
{QString msg ui-lineEdit-text(); //发送信息QByteArray str msg.toUtf8();QString targetIp ui-comboBox-currentText(); //目标IP就是主机地址的ipQHostAddress targetAddr(targetIp);quint16 targetPort ui-spinBox_2-value(); //目标端口udpScoket-writeDatagram(str, targetAddr, targetPort);//发出数据报ui-textEdit-append([out] msg);ui-lineEdit-clear();ui-lineEdit-setFocus();}
//广播信息
void MainWindow::on_pushButton_2_clicked()
{quint16 targetPort ui-spinBox_2-value(); //目标端口QString msgui-lineEdit-text();QByteArray str msg.toUtf8();udpScoket-writeDatagram(str, QHostAddress::Broadcast, targetPort);//发出数据报ui-textEdit-append([broadcast] msg);ui-lineEdit-clear();ui-lineEdit-setFocus();}代码化
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_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 QVBoxLayoutnamespace Ui {class MainWindow;
}class MainWindow : public QMainWindow {Q_OBJECTpublic:explicit MainWindow(QWidget* parent 0);~MainWindow();private slots:void slotActBindPort();void slotActUnbindPort();void slotActClearText();void slotActQuit();void slotSocketStateChanged(QAbstractSocket::SocketState socketState);void slotBtnSend();void slotBtnBroad();void slotSocketReadyRead(); //读取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.cpp
#include mainwindow.h
#include QToolBar
#include ui_mainwindow.hMainWindow::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-toolBar-setToolButtonStyle(Qt::ToolButtonTextBesideIcon);m_pActBindPort new QAction(QIcon(:/new/Check.png), QStringLiteral(绑定端口), this);m_pActUnbindPort new QAction(QIcon(:/new/Break.png), QStringLiteral(结束绑定), this);m_pActClearText new QAction(QIcon(:/new/remove.png), QStringLiteral(清空文本), this);m_pActQuit new QAction(QIcon(:/new/back.png), QStringLiteral(退出), this);ui-toolBar-addAction(m_pActBindPort);ui-toolBar-addAction(m_pActUnbindPort);ui-toolBar-addSeparator();ui-toolBar-addAction(m_pActClearText);ui-toolBar-addSeparator();ui-toolBar-addAction(m_pActQuit);//界面布局m_pCentralWidget new QWidget(this);QHBoxLayout* HLay1 new QHBoxLayout;m_pLabBindPort new QLabel(QStringLiteral(绑定端口), m_pCentralWidget);m_pSpinBindPort new QSpinBox(m_pCentralWidget);m_pSpinBindPort-setMinimum(1);m_pSpinBindPort-setMaximum(65535);m_pSpinBindPort-setValue(3200);m_PLabTargetAddr new QLabel(QStringLiteral(目标地址), m_pCentralWidget);m_pComboTargetAddr new QComboBox(m_pCentralWidget);m_pLabTargetPort new QLabel(QStringLiteral(目标端口), m_pCentralWidget);m_pSpinTargetPort new QSpinBox(m_pCentralWidget);m_pSpinTargetPort-setMinimum(1);m_pSpinTargetPort-setMaximum(65535);m_pSpinTargetPort-setValue(1600);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 new QLineEdit(m_pCentralWidget);m_pBtnSend new QPushButton(QStringLiteral(发送消息), m_pCentralWidget);m_pBtnBroad new QPushButton(QStringLiteral(广播消息), m_pCentralWidget);HLay2-addWidget(m_pLineEdit);HLay2-addWidget(m_pBtnSend);HLay2-addWidget(m_pBtnBroad);QVBoxLayout* VLay new QVBoxLayout(m_pCentralWidget); //主布局必须设置parent否则不会显示布局// QVBoxLayout* VLay new QVBoxLayout();VLay-addLayout(HLay1);VLay-addLayout(HLay2);m_pPlainText new QPlainTextEdit(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 new QUdpSocket(this);//状态栏m_pLabState new QLabel(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;
}void MainWindow::slotActBindPort()
{quint16 port m_pSpinBindPort-value(); //本机UDP端口if (m_pUdpSocket-bind(port)) {m_pPlainText-appendPlainText(QStringLiteral(**已成功绑定));m_pPlainText-appendPlainText(QStringLiteral(绑定端口) QString::number(m_pUdpSocket-localPort()));//使能m_pActBindPort-setEnabled(false);m_pActUnbindPort-setEnabled(true);} else {m_pPlainText-appendPlainText(QStringLiteral(绑定失败));}
}void MainWindow::slotActUnbindPort() {m_pUdpSocket-abort(); //解除绑定m_pPlainText-appendPlainText(QStringLiteral(**已解除绑定));m_pActBindPort-setEnabled(true);m_pActUnbindPort-setEnabled(false);
}void MainWindow::slotActClearText() { m_pPlainText-clear(); }void MainWindow::slotActQuit() {QMessageBox::StandardButton button QMessageBox::question(this, , QStringLiteral(是否要退出));if (button QMessageBox::StandardButton::Yes)this-close();
}void MainWindow::slotSocketStateChanged(QAbstractSocket::SocketState socketState) {switch (socketState){case QAbstractSocket::UnconnectedState: m_pLabState-setText(QStringLiteral(socket状态UnconnectedState)); break;case QAbstractSocket::HostLookupState: m_pLabState-setText(QStringLiteral(socket状态HostLookupState)); break;case QAbstractSocket::ConnectingState: m_pLabState-setText(QStringLiteral(socket状态ConnectingState)); break;case QAbstractSocket::ConnectedState: m_pLabState-setText(QStringLiteral(socket状态ConnectedState)); break;case QAbstractSocket::BoundState: m_pLabState-setText(QStringLiteral(socket状态BoundState)); break;case QAbstractSocket::ClosingState: m_pLabState-setText(QStringLiteral(socket状态ClosingState)); break;default: break;}}void MainWindow::slotBtnSend()
{QString msg m_pLineEdit-text();QByteArray str msg.toUtf8();QString targetIp m_pComboTargetAddr-currentText(); //目标IPQHostAddress targetAddr(targetIp);quint16 targetPort m_pSpinTargetPort-value(); //目标端口m_pUdpSocket-writeDatagram(str, targetAddr, targetPort);m_pPlainText-appendPlainText([out] msg);m_pLineEdit-clear();m_pLineEdit-setFocus();}void MainWindow::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();}void MainWindow::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 ;QListQHostAddress 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;
}
结果 发现自己用UI设计时发送信息总会出现两个发送信号并且有一个是空白的暂时还没有找到问题所在之处嘤嘤嘤~(/≧▽≦)/
5. UDP组播代码示例
5.1 组播的特性
组播报文的目的地址使用D类IP地址D类地址不能出现在IP报文的地址字段。用同一个IP多播地址接收多播数据报的所有主机构成一个组称为多播组或组播组。所有的信息接收者都加入一个组内并且一旦加入后流向组地址的数据报立即开始向接收者传输组中的所有的成员都能接收到数据报。组中的成员是动态的主机可以在任何人时间加入和离开组。
关于组播IP地址有以下约定
224.0.0.0 ~ 224.0.0.255 为预留的组播地址永久组地址地址224.0.0.0保留不做分配其他地址供路由协议使用。224.0.1.0 ~ 224.0.1.255 是公用组播地址可以用于Internet。224.0.2.0 ~ 238.255.255.255 为用户可用的组播地址临时组地址全网范围内有效。239.0.0.0 ~ 239.255.255.255 为本地管理组播地址仅在特定的本地范围内有效。所以若是在家庭或办公室局域网内测试UDP组播功能可以使用这些IP。 原文链接https://blog.csdn.net/WL0616/article/details/129050373 常量定义 值 描述 QUdpSocket::ShareAddress 0x1 1、允许其他服务绑定同样的地址和端口 2、当多进程通过监听同一地址和端口进而共享单个服务的负载时将十分有用(例如一个拥有几个预先建立的监听者的WEB服务器能够改善响应时间)。不过由于任何服务都允许重新绑定(rebind)该选项应该引起某些安全上的考虑 3、需要注意的是把该选项和ReuseAddressHint结合也会允许你的服务重新绑定一个已存在的共享地址 4、在Unix上该选项等同于SO_REUSEADDR在Windows上该选项被忽略 QUdpSocket::DontShareAddress 0x2 1、采用专有的方式绑定某个地址和端口其他任何服务都不能再重新绑定 2、通过该选项确保绑定成功指定的服务将是地址和端口唯一监听者就算是拥有ReuseAddressHint的服务也不允许重新绑定 3、在安全性上该选项优于ShareAddress但是在某些操作系统上需要管理员的权限才能运行 4、在Unix和Mac OS上绑定地址和端口的默认行为是非共享所以该选项会被忽略在Windows上等同于SO_EXCLUSIVEADDRUSE套接字选项 QUdpSocket::ReuseAddressHint 0x4 1、为QUdpSocke提供提示即在地址和端口已经被其他套接字绑定的情况下也应该试着重新绑定 2、在Unix上该选项被忽略在Windows上等同于SO_REUSEADDR 套接字选项 QUdpSocket::DefaultForPlatform 0x0 1、当前平台的默认选项 2、在Unix和Mac OS上该选项等同于DontShareAddress ReuseAddressHint在Windows上等同于ShareAddress
5.2主要程序
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_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 QVBoxLayoutnamespace Ui {class MainWindow;
}class MainWindow : public QMainWindow {Q_OBJECTpublic:explicit MainWindow(QWidget* parent 0);~MainWindow();private slots:void slotActJoinMulti();void slotActLeaveMulti();void slotActClearText();void slotActQuit();void slotSocketStateChanged(QAbstractSocket::SocketState socketState);void slotBtnMultiMsg();void slotReadyRead();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.cpp
#include mainwindow.h#include ui_mainwindow.hMainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {ui-setupUi(this);this-setWindowTitle(QStringLiteral(UDP Multicast));//工具栏ui-mainToolBar-setToolButtonStyle(Qt::ToolButtonTextBesideIcon);m_pActJoinMulti new QAction(QIcon(:/new/prefix1/res/添加群组.png), QStringLiteral(加入组播), this);m_pActLeaveMulti new QAction(QIcon(:/new/prefix1/res/退出群组.png), QStringLiteral(退出组播), this);m_pActClearText new QAction(QIcon(:/new/prefix1/res/清空.png), QStringLiteral(清空文本), this);m_pActQuit new QAction(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 new QWidget(this);m_pLabPort new QLabel(QStringLiteral(组播端口), m_pCentralWidget);m_pSpinPort new QSpinBox(m_pCentralWidget);m_pSpinPort-setMinimum(1);m_pSpinPort-setMaximum(65535);m_pSpinPort-setValue(3200);m_pLabAddr new QLabel(QStringLiteral(组播地址), m_pCentralWidget);m_pComboAddr new QComboBox(m_pCentralWidget);m_pComboAddr-setEditable(true); //下拉框可编辑输入m_pComboAddr-addItem(239.0.0.1);// 正则匹配 D类IP224.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 new QRegExpValidator(regExp, this);m_pComboAddr-setValidator(pValidator);QHBoxLayout* HLay1 new QHBoxLayout();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 new QLineEdit(m_pCentralWidget);m_pBtnSendMulti new QPushButton(QStringLiteral(组播消息), m_pCentralWidget);QHBoxLayout* HLay2 new QHBoxLayout();HLay2-addWidget(m_pLineEdit, 4);HLay2-addWidget(m_pBtnSendMulti, 1);m_pPlainText new QPlainTextEdit(m_pCentralWidget);QVBoxLayout* VLay new QVBoxLayout(m_pCentralWidget);VLay-addLayout(HLay1);VLay-addLayout(HLay2);VLay-addWidget(m_pPlainText);this-setCentralWidget(m_pCentralWidget);this-setLayout(VLay);//状态栏m_pLabState new QLabel(QStringLiteral(socket状态), this);m_pLabState-setMinimumWidth(150);ui-statusBar-addWidget(m_pLabState);QString str getLocalIP();this-setWindowTitle(this-windowTitle() ---IP: str);m_pUdpSocket new QUdpSocket(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; }void MainWindow::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(**绑定端口失败);}
}void MainWindow::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(**已退出组播解除端口绑定);
}void MainWindow::slotActClearText() { m_pPlainText-clear(); }void MainWindow::slotActQuit() {QMessageBox::StandardButton button QMessageBox::question(this, , 是否退出);if (QMessageBox::StandardButton::Yes button) {this-close();}
}void MainWindow::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;}
}void MainWindow::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();
}void MainWindow::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);QListQHostAddress 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;
}结果 原文链接https://blog.csdn.net/WL0616/article/details/129050373