#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QUdpSocket>
#include <QHostInfo>
#pragma execution_character_set("utf-8")
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QLabel *labSocketState;
QUdpSocket *udpsocket;
QHostAddress groupAddress; //组播地址
QString getLocalIP(); //获取本机IP地址
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
void onSocketStateChange(QAbstractSocket::SocketState socketState);
void onSocketReadyReady();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
labSocketState = new QLabel("Socket 状态");
labSocketState->setMinimumWidth(200);
ui->statusBar->addWidget(labSocketState);
QString LocalIP =getLocalIP();
this->setWindowTitle(this->windowTitle() + "----本机IP:"+ LocalIP);
udpsocket = new QUdpSocket(this);
udpsocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);
//将socket的QAbstractSocket::MulticastTtlOption设为1,MulticastTtlOption是UDP组播的数据包周期
//数据包每跨一个路由会减1,缺省值为1,表示多播数据包只能在同一路由下的局域网内传播
connect(udpsocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
connect(udpsocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyReady()));
}
MainWindow::~MainWindow()
{
delete ui;
}
QString MainWindow::getLocalIP()
{
QString hostname = QHostInfo::localHostName(); //本地主机名
//ui->plainTextEdit->appendPlainText("本地主机名:"+hostname+"\n");
QHostInfo hostinfo = QHostInfo::fromName(hostname); //本机IP
QList<QHostAddress> addList = hostinfo.addresses();// IP地址列表
if(!addList.isEmpty())
{
for(int i =0;i<addList.count();i++)
{
QHostAddress aHost = addList.at(i);
return aHost.toString();
}
}
}
//加入组播
void MainWindow::on_pushButton_clicked()
{
QString IP = ui->lineEdit->text();
groupAddress = QHostAddress(IP);
quint16 groupPort = ui->spinBox->value(); //端口
if(udpsocket->bind(QHostAddress::AnyIPv4,groupPort,QUdpSocket::ShareAddress))
{
udpsocket->joinMulticastGroup(groupAddress);
ui->plainTextEdit->appendPlainText("加入组播成功");
ui->plainTextEdit->appendPlainText("组播地址IP:"+IP);
ui->plainTextEdit->appendPlainText("绑定端口:"+QString::number(groupPort));
ui->pushButton->setEnabled(false);
ui->pushButton_2->setEnabled(true);
//ui->comboBox->setEnabled(false);
}
else
{
ui->plainTextEdit->appendPlainText("绑定端口失败");
}
}
//退出组播
void MainWindow::on_pushButton_2_clicked()
{
udpsocket->leaveMulticastGroup(groupAddress);//退出组播
udpsocket->abort(); //解除绑定
ui->pushButton->setEnabled(true);
ui->pushButton_2->setEnabled(false);
// ui->comboBox->setEnabled(true);
ui->plainTextEdit->appendPlainText("已退出组播,解除端口绑定");
}
//clear
void MainWindow::on_pushButton_3_clicked()
{
ui->plainTextEdit->clear();
}
//quit
void MainWindow::on_pushButton_4_clicked()
{
this->close();
}
//发送
void MainWindow::on_pushButton_5_clicked()
{
quint16 groupPort = ui->spinBox->value();
QString msg = ui->lineEdit_2->text();
QByteArray datagram = msg.toUtf8();
udpsocket->writeDatagram(datagram,groupAddress,groupPort);
ui->plainTextEdit->appendPlainText("发送组播消息"+msg);
ui->lineEdit_2->clear();
ui->lineEdit_2->setFocus();
}
void MainWindow::onSocketStateChange(QAbstractSocket::SocketState socketState)
{
if(socketState==QAbstractSocket::BoundState)
{
}
}
void MainWindow::onSocketReadyReady()
{
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 = "[From"+ peerAddr.toString()+":"+ QString ::number(peerPort)+"]";
ui->plainTextEdit->appendHtml(peer);
}
}