From 488485ee498366c4d9da2732c858c1c186989966 Mon Sep 17 00:00:00 2001 From: touwoyimuli Date: Mon, 2 Dec 2019 00:00:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20UDP=20=E7=9A=84=E7=9A=84=E5=8D=95?= =?UTF-8?q?=E6=92=AD=E5=92=8C=E5=B9=BF=E6=92=AD=E5=8A=9F=E8=83=BD=E5=B7=B2?= =?UTF-8?q?=E7=BB=8F=E5=AE=8C=E5=85=A8=E5=AE=9E=E7=8E=B0=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QtUdpEx/ExTrans/ExTrans.cpp | 134 +++++++++++++++++++++++++++++++++++- QtUdpEx/ExTrans/ExTrans.h | 28 ++++++-- QtUdpEx/ExTrans/ExTrans.pro | 2 +- QtUdpEx/ExTrans/ExTrans.ui | 17 +++-- 4 files changed, 169 insertions(+), 12 deletions(-) diff --git a/QtUdpEx/ExTrans/ExTrans.cpp b/QtUdpEx/ExTrans/ExTrans.cpp index cb3b782..dbf419f 100644 --- a/QtUdpEx/ExTrans/ExTrans.cpp +++ b/QtUdpEx/ExTrans/ExTrans.cpp @@ -22,35 +22,165 @@ #include "ExTrans.h" #include "ui_ExTrans.h" +#include + ExTrans::ExTrans(QWidget *parent) : QMainWindow(parent), ui(new Ui::ExTrans) { ui->setupUi(this); setWindowTitle("Tcp通信:unicast(单播) + broadcast(广播)的使用"); + + QString hostName = QHostInfo::localHostName(); + QString ip = getLocalIp(); + ui->plainTextEdit->appendPlainText("主机名称:" + hostName + "\n主机IP:" + ip + "\n"); + + m_labSocketState = new QLabel("Socket状态:"); + m_labSocketState->setMinimumWidth(200); + ui->statusBar->addWidget(m_labSocketState); + + ui->comboBoxIp->addItem(getLocalIp()); + m_udpSocket = new QUdpSocket(this); + + connect(m_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChange(QAbstractSocket::SocketState))); + onSocketStateChange(m_udpSocket->state()); + connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(onSocketReadyRead())); } ExTrans::~ExTrans() { delete ui; } - +//绑定端口 void ExTrans::on_actBind_triggered() { + quint16 port = ui->spinBoxBind->value(); //本机UDP端口 + if (m_udpSocket->bind(port)) { //端口绑定成功 + ui->plainTextEdit->appendPlainText("端口绑定成功:" + QString::number(m_udpSocket->localPort())); + ui->actBind->setEnabled(false); + ui->actDisbind->setEnabled(true); + } else { + ui->plainTextEdit->appendPlainText("端口绑定失败"); + } } +//解除绑定 void ExTrans::on_actDisbind_triggered() { + m_udpSocket->abort(); //断开,中止套接字 + ui->plainTextEdit->appendPlainText("端口解除绑定成功"); + ui->actBind->setEnabled(true); + ui->actDisbind->setEnabled(false); } +//清除文本信息 void ExTrans::on_actClean_triggered() { - + ui->plainTextEdit->clear(); } +//关闭程序 void ExTrans::on_actQuit_triggered() { close(); } + +//单播消息 +void ExTrans::on_btnUnicast_clicked() +{ + QString targetIp = ui->comboBoxIp->currentText(); + QHostAddress targetAddr(targetIp); //目标 Ip + quint16 targetPort = ui->spinBoxPort->value(); //目标 port + QString msg = ui->lineEdit->text(); //发送的消息 + + QByteArray str = msg.toUtf8(); + m_udpSocket->writeDatagram(str, targetAddr, targetPort); //发送数据报 + + ui->plainTextEdit->appendPlainText(QString("[Send: ] %1").arg(msg)); + ui->lineEdit->clear(); + ui->lineEdit->setFocus(); +} + +//广播消息 +void ExTrans::on_btnBroadcast_clicked() +{ + quint16 targetPort = ui->spinBoxPort->value(); //目标 port + QString msg = ui->lineEdit->text(); //发送的消息 + + QByteArray str = msg.toUtf8(); + m_udpSocket->writeDatagram(str, QHostAddress::Broadcast, targetPort); //发送 数据报 给所有IP + + ui->plainTextEdit->appendPlainText(QString("[广播: ] %1").arg(msg)); + ui->lineEdit->clear(); + ui->lineEdit->setFocus(); +} + +//socket 状态发生变化 +void ExTrans::onSocketStateChange(QAbstractSocket::SocketState socketState) +{ + switch (socketState) { + case QAbstractSocket::UnconnectedState: + m_labSocketState->setText("socket状态:UnconnectedState"); + break; + case QAbstractSocket::HostLookupState: + m_labSocketState->setText("socket状态:HostLookupState"); + break; + case QAbstractSocket::ConnectingState: + m_labSocketState->setText("socket状态:ConnectingState"); + break; + case QAbstractSocket::ConnectedState: + m_labSocketState->setText("socket状态:ConnectedState"); + break; + case QAbstractSocket::BoundState: + m_labSocketState->setText("socket状态:BoundState"); + break; + case QAbstractSocket::ClosingState: + m_labSocketState->setText("socket状态:ClosingState"); + break; + case QAbstractSocket::ListeningState: + m_labSocketState->setText("socket状态:ListeningState"); + break; + default: + m_labSocketState->setText("socket状态:其他未知状态..."); + break; + } +} + +//读取 socket 传入的数据 +void ExTrans::onSocketReadyRead() +{ + while (m_udpSocket->hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(m_udpSocket->pendingDatagramSize()); + + QHostAddress peerAddr; + quint16 peerPort; + + m_udpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort); //读取数据包,消息+来自的Ip和port + QString str = datagram.data(); + QString peer = QString("[From: %1 %2] %3").arg(peerAddr.toString()).arg(QString::number(peerPort)).arg(str); + ui->plainTextEdit->appendPlainText(peer); + } +} + +//获取本机IP +QString ExTrans::getLocalIp() +{ + QString hostName = QHostInfo::localHostName(); + QHostInfo hostInfo = QHostInfo::fromName(hostName); + QString Ip = ""; + + if (hostInfo.addresses().isEmpty()) + return 0; + + foreach (QHostAddress addr, hostInfo.addresses()) { + if (addr.protocol() == QAbstractSocket::IPv4Protocol) { + Ip = addr.toString(); + break; + } + } + + return Ip; +} diff --git a/QtUdpEx/ExTrans/ExTrans.h b/QtUdpEx/ExTrans/ExTrans.h index f0c8e57..0d54224 100644 --- a/QtUdpEx/ExTrans/ExTrans.h +++ b/QtUdpEx/ExTrans/ExTrans.h @@ -23,11 +23,20 @@ #define EXTRANS_H #include +#include +#include +#include namespace Ui { class ExTrans; } +/*! + * \class ExTrans 一个UDP的Deam测试,同时测试单播和广播 + * \brief 因为是在同一台电脑测试,所以IP相同,需要绑定两个不同端口的,这样不会冲突; + * 若是两台电脑进行测试,那么可以约定使用相同的端口号,使用不同的IP;来进行通讯 + */ + class ExTrans : public QMainWindow { Q_OBJECT @@ -37,13 +46,24 @@ public: ~ExTrans(); private slots: - void on_actBind_triggered(); - void on_actDisbind_triggered(); - void on_actClean_triggered(); - void on_actQuit_triggered(); + void on_actBind_triggered(); //绑定端口 + void on_actDisbind_triggered(); //解除绑定 + void on_actClean_triggered(); //清除文本信息 + void on_actQuit_triggered(); //关闭程序 + void on_btnUnicast_clicked(); //单播消息 + void on_btnBroadcast_clicked(); //广播消息 + + void onSocketStateChange(QAbstractSocket::SocketState socketState); //socket 状态发生变化 + void onSocketReadyRead(); //读取 socket 传入的数据 + +private: + QString getLocalIp(); //获取本机IP private: Ui::ExTrans *ui; + + QLabel* m_labSocketState; + QUdpSocket* m_udpSocket; }; #endif // EXTRANS_H diff --git a/QtUdpEx/ExTrans/ExTrans.pro b/QtUdpEx/ExTrans/ExTrans.pro index 1708512..346af64 100644 --- a/QtUdpEx/ExTrans/ExTrans.pro +++ b/QtUdpEx/ExTrans/ExTrans.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui +QT += core gui network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets diff --git a/QtUdpEx/ExTrans/ExTrans.ui b/QtUdpEx/ExTrans/ExTrans.ui index 3023f94..b524a85 100644 --- a/QtUdpEx/ExTrans/ExTrans.ui +++ b/QtUdpEx/ExTrans/ExTrans.ui @@ -27,7 +27,7 @@ - + 65000 @@ -48,7 +48,14 @@ - + + + true + + + 129.0.0.1 + + @@ -62,7 +69,7 @@ - + 65000 @@ -81,14 +88,14 @@ - + 单播发送 - + 广播发送