diff --git a/QtUdpEx/ExMulticast/ExMulticast.cpp b/QtUdpEx/ExMulticast/ExMulticast.cpp new file mode 100644 index 0000000..91d4a17 --- /dev/null +++ b/QtUdpEx/ExMulticast/ExMulticast.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2019 ~ 2019 touwoyimuli. All rights reserved. + * + * Author: touwoyimuli + * + * github: https://github.com/touwoyimuli + * blogs: https://touwoyimuli.github.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "ExMulticast.h" +#include "ui_ExMulticast.h" + +ExMulticast::ExMulticast(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::ExMulticast) +{ + ui->setupUi(this); + setWindowTitle("Udp通信:multicate(组播)的使用"); + + 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); //用于通讯使用的 Socket + //Multicast路由层次,1表示只在同一局域网内 + //组播TTL: 生存时间,每跨1个路由会减1,多播无法跨过大多数路由所以为1 + //默认值是1,表示数据包只能在本地的子网中传送。 + m_udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 1); + + + + connect(m_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChange(QAbstractSocket::SocketState))); + onSocketStateChange(m_udpSocket->state()); + connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(onSocketReadyRead())); +} + +ExMulticast::~ExMulticast() +{ + delete ui; +} + +void ExMulticast::on_actStart_triggered() +{ + QString ip = ui->comboBoxIp->currentText(); + m_groupAddress = QHostAddress(ip); + quint16 port = ui->spinBoxBind->value(); + + if (m_udpSocket->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress)) { //绑定端口 + m_udpSocket->joinMulticastGroup(m_groupAddress); //加入多播组 + + ui->plainTextEdit->appendPlainText("[用户:" + getLocalIp() +"] 加入组播(组播地址:" + ip + " 端口:" + QString::number(port) + ")成功"); + ui->actStart->setEnabled(false); + ui->actStop->setEnabled(true); + } else { + ui->plainTextEdit->appendPlainText("[用户:" + getLocalIp() +"] 加入组播(组播地址:" + ip + " 端口:" + QString::number(port) + ")失败"); + } +} + +void ExMulticast::on_actStop_triggered() +{ + m_udpSocket->leaveMulticastGroup(m_groupAddress); //退出组播 + m_udpSocket->abort(); //解除绑定 + ui->plainTextEdit->appendPlainText("[用户:" + getLocalIp() +"] 退出组播成功"); + ui->actStart->setEnabled(true); + ui->actStop->setEnabled(false); +} + +void ExMulticast::on_actClear_triggered() +{ + ui->plainTextEdit->clear(); +} + +void ExMulticast::on_actQuit_triggered() +{ + close(); +} + +void ExMulticast::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; + } +} + +void ExMulticast::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); + } +} + +QString ExMulticast::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; +} + +void ExMulticast::on_btnSend_clicked() +{ + quint16 port = ui->spinBoxBind->value(); + QString msg = ui->lineEdit->text(); + QByteArray datagram = msg.toUtf8(); + + m_udpSocket->writeDatagram(datagram, m_groupAddress, port); +// m_udpSocket->writeDatagram(datagram.data(), datagram.size(), m_groupAddress, port); + ui->plainTextEdit->appendPlainText("[multicst] " + msg); + ui->lineEdit->clear(); + ui->lineEdit->setFocus(); +} diff --git a/QtUdpEx/ExMulticast/ExMulticast.h b/QtUdpEx/ExMulticast/ExMulticast.h new file mode 100644 index 0000000..7288f19 --- /dev/null +++ b/QtUdpEx/ExMulticast/ExMulticast.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 ~ 2019 touwoyimuli. All rights reserved. + * + * Author: touwoyimuli + * + * github: https://github.com/touwoyimuli + * blogs: https://touwoyimuli.github.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef EXMULTICAST_H +#define EXMULTICAST_H + +#include +#include +#include +#include +#include + +namespace Ui { +class ExMulticast; +} + +class ExMulticast : public QMainWindow +{ + Q_OBJECT + +public: + explicit ExMulticast(QWidget *parent = nullptr); + ~ExMulticast(); + +private slots: + void on_actStart_triggered(); + void on_actStop_triggered(); + void on_actClear_triggered(); + void on_actQuit_triggered(); + + void onSocketStateChange(QAbstractSocket::SocketState socketState); //socket 状态发生变化 + void onSocketReadyRead(); //读取 socket 传入的数据 + void on_btnSend_clicked(); + +private: + QString getLocalIp(); //获取本机IP + +private: + Ui::ExMulticast *ui; + + QUdpSocket* m_udpSocket; //用于通讯的 socket + QLabel* m_labSocketState; + QHostAddress m_groupAddress; //组播地址 +}; + +#endif // EXMULTICAST_H diff --git a/QtUdpEx/ExMulticast/ExMulticast.pro b/QtUdpEx/ExMulticast/ExMulticast.pro new file mode 100644 index 0000000..29a54c4 --- /dev/null +++ b/QtUdpEx/ExMulticast/ExMulticast.pro @@ -0,0 +1,55 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-12-04T21:34:23 +# +#------------------------------------------------- + +QT += core gui network + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = ExMulticast +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +CONFIG += c++11 + +SOURCES += \ + main.cpp \ + ExMulticast.cpp + +HEADERS += \ + ExMulticast.h + +FORMS += \ + ExMulticast.ui + +macx { +ICON = images/icon.icns +} + +unix:!macx{ +# linux only +} + +win32 { +RC_ICONS = images/icon.ico +} + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +RESOURCES += \ + resources.qrc diff --git a/QtUdpEx/ExMulticast/ExMulticast.ui b/QtUdpEx/ExMulticast/ExMulticast.ui new file mode 100644 index 0000000..f808002 --- /dev/null +++ b/QtUdpEx/ExMulticast/ExMulticast.ui @@ -0,0 +1,190 @@ + + + ExMulticast + + + + 0 + 0 + 522 + 396 + + + + ExMulticast + + + + + + + + + + + 组播端口: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 65000 + + + 8888 + + + + + + + + + + + 组播地址: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + true + + + 239.255.43.21 + + + + 239.255.43.21 + + + + + 239.255.100.1 + + + + + 239.255.255.100 + + + + + + + + + + + + + + + + + 组播发送 + + + + + + + + + 239.0.0.0~239.255.255.255为本地管理组播地址范围 + + + + + + + + + 0 + 0 + 522 + 25 + + + + + + Qt::ToolButtonTextBesideIcon + + + TopToolBarArea + + + false + + + + + + + + + + + + + :/images/Image4.png:/images/Image4.png + + + 加入 + + + 加入组播 + + + + + + :/images/Image5.png:/images/Image5.png + + + 退出 + + + 退出组播 + + + + + + :/images/Image1.png:/images/Image1.png + + + 清空 + + + 清空文本内容 + + + + + + :/images/Image2.jpg:/images/Image2.jpg + + + 退出 + + + 退出程序 + + + + + + + + + diff --git a/QtUdpEx/ExMulticast/images/Image1.png b/QtUdpEx/ExMulticast/images/Image1.png new file mode 100644 index 0000000..c2c4e0d Binary files /dev/null and b/QtUdpEx/ExMulticast/images/Image1.png differ diff --git a/QtUdpEx/ExMulticast/images/Image2.jpg b/QtUdpEx/ExMulticast/images/Image2.jpg new file mode 100644 index 0000000..46070af Binary files /dev/null and b/QtUdpEx/ExMulticast/images/Image2.jpg differ diff --git a/QtUdpEx/ExMulticast/images/Image3.png b/QtUdpEx/ExMulticast/images/Image3.png new file mode 100644 index 0000000..c9045da Binary files /dev/null and b/QtUdpEx/ExMulticast/images/Image3.png differ diff --git a/QtUdpEx/ExMulticast/images/Image4.png b/QtUdpEx/ExMulticast/images/Image4.png new file mode 100644 index 0000000..0319033 Binary files /dev/null and b/QtUdpEx/ExMulticast/images/Image4.png differ diff --git a/QtUdpEx/ExMulticast/images/Image5.png b/QtUdpEx/ExMulticast/images/Image5.png new file mode 100644 index 0000000..95ecf80 Binary files /dev/null and b/QtUdpEx/ExMulticast/images/Image5.png differ diff --git a/QtUdpEx/ExMulticast/images/Image6.png b/QtUdpEx/ExMulticast/images/Image6.png new file mode 100644 index 0000000..d246ada Binary files /dev/null and b/QtUdpEx/ExMulticast/images/Image6.png differ diff --git a/QtUdpEx/ExMulticast/images/icon.icns b/QtUdpEx/ExMulticast/images/icon.icns new file mode 100755 index 0000000..4f20853 Binary files /dev/null and b/QtUdpEx/ExMulticast/images/icon.icns differ diff --git a/QtUdpEx/ExMulticast/images/icon.ico b/QtUdpEx/ExMulticast/images/icon.ico new file mode 100755 index 0000000..0ee0568 Binary files /dev/null and b/QtUdpEx/ExMulticast/images/icon.ico differ diff --git a/QtUdpEx/ExMulticast/main.cpp b/QtUdpEx/ExMulticast/main.cpp new file mode 100644 index 0000000..9371344 --- /dev/null +++ b/QtUdpEx/ExMulticast/main.cpp @@ -0,0 +1,11 @@ +#include "ExMulticast.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + ExMulticast w; + w.show(); + + return a.exec(); +} diff --git a/QtUdpEx/ExMulticast/resources.qrc b/QtUdpEx/ExMulticast/resources.qrc new file mode 100644 index 0000000..8774523 --- /dev/null +++ b/QtUdpEx/ExMulticast/resources.qrc @@ -0,0 +1,8 @@ + + + images/Image1.png + images/Image2.jpg + images/Image4.png + images/Image5.png + +