十四、Qt主机信息与网络编程

一、主机信息

1、主机信息接口

  • QHostInfo:获取主机名称和IP地址
  • QNetWorkInterface:获取主机的所有网络接口,包括子网掩码和广播地址等

(1)使用

项目添加模块
QT       += network

2、实现程序

在这里插入图片描述

(1)创建项目,基于QDialog

在这里插入图片描述

(2)实现功能

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

#include <QHostInfo>
#include <QNetworkInterface>

namespace Ui
{
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

private:
    QString protocolName(QAbstractSocket::NetworkLayerProtocol protocol);

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();

private slots:
    void on_btnHostIP_clicked();

    void on_btnClearText_clicked();

    void on_btnDnsIP_clicked();

    void on_lookUpHostInfo(QHostInfo host);

    void on_btnAllAddresses_clicked();

    void on_btnAllInterface_clicked();

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"



QString Dialog::protocolName(QAbstractSocket::NetworkLayerProtocol protocol)
{
    switch (protocol)
    {
    case QAbstractSocket::IPv4Protocol:
        return "IPv4 Protocol";
        break;
    case QAbstractSocket::IPv6Protocol:
        return "IPv6 Protocol";
        break;
    case QAbstractSocket::AnyIPProtocol:
        return "AnyIP Protocol";
        break;
    default:
        return "Unknown Protocol";
        break;
    }
}

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::on_btnHostIP_clicked()
{
    QString hostName = QHostInfo::localHostName();
    ui->plainTextEdit->appendPlainText(hostName);

    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QList<QHostAddress> addList = hostInfo.addresses();
    foreach (auto aHost, addList)
    {
        if(ui->checkBox->isChecked())
        {
            if(aHost.protocol() == QAbstractSocket::IPv4Protocol)
            {
                ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol()));
                ui->plainTextEdit->appendPlainText("本机IP地址:" + aHost.toString());
                ui->plainTextEdit->appendPlainText("");
            }
        }
        else
        {
            ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol()));
            ui->plainTextEdit->appendPlainText("本机IP地址:" + aHost.toString());
            ui->plainTextEdit->appendPlainText("");
        }
    }
}

void Dialog::on_btnClearText_clicked()
{
    ui->plainTextEdit->clear();
}

void Dialog::on_btnDnsIP_clicked()
{
    // 异步方式
    QString hostName = ui->lineEdit->text();
    ui->plainTextEdit->appendPlainText("正在查询主机信息:" + hostName);
    QHostInfo::lookupHost(hostName, this, SLOT(on_lookUpHostInfo(QHostInfo)));
}

void Dialog::on_lookUpHostInfo(QHostInfo host)
{
    QList<QHostAddress> addList = host.addresses();
    foreach (auto aHost, addList)
    {
        if(ui->checkBox->isChecked())
        {
            if(aHost.protocol() == QAbstractSocket::IPv4Protocol)
            {
                ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol()));
                ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString());
                ui->plainTextEdit->appendPlainText("");
            }
        }
        else
        {
            ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol()));
            ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString());
            ui->plainTextEdit->appendPlainText("");
        }
    }
}

void Dialog::on_btnAllAddresses_clicked()
{
    QList<QHostAddress> addList = QNetworkInterface::allAddresses();
    foreach (auto aHost, addList)
    {
        if(ui->checkBox->isChecked())
        {
            if(aHost.protocol() == QAbstractSocket::IPv4Protocol)
            {
                ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol()));
                ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString());
                ui->plainTextEdit->appendPlainText("");
            }
        }
        else
        {
            ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol()));
            ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString());
            ui->plainTextEdit->appendPlainText("");
        }
    }
}

void Dialog::on_btnAllInterface_clicked()
{
    QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();
    foreach (auto aInterface, list)
    {
        if(!aInterface.isValid())
        {
            continue;
        }
        ui->plainTextEdit->appendPlainText("设备名称: " + aInterface.humanReadableName());
        ui->plainTextEdit->appendPlainText("硬件地址: " + aInterface.hardwareAddress());
        QList<QNetworkAddressEntry> entryList = aInterface.addressEntries();
        foreach (auto aEntry, entryList)
        {
            ui->plainTextEdit->appendPlainText("  IP地址: " + aEntry.ip().toString());
            ui->plainTextEdit->appendPlainText("  子网掩码: " + aEntry.netmask().toString());
            ui->plainTextEdit->appendPlainText("  广播地址: " + aEntry.broadcast().toString());
        }
        ui->plainTextEdit->appendPlainText("");
    }
}

在这里插入图片描述

二、TCP通信

TCP是一种被大多数Internet网络协议(HTTP、FTP等)用于数据传输的低级网络协议,是可靠的、面向流、面向连接的传输协议。

1、相关类

(1)继承关系

QIODevice
	QAbstractSocket
		QTcpSocket
			QSctpSocket
			QSslSocket // 加密
		QUdpSocket			

2、实现服务端程序

在这里插入图片描述

(1)创建项目

(2)添加图标资源

在这里插入图片描述

(3)实现服务器功能

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QTcpServer>
#include <QLabel>

namespace Ui
{
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QLabel *labListen;
    QLabel *labSocketState;

    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void closeEvent(QCloseEvent *event);

private:
    QString getLocalIP();

private slots:
    void on_newConnection();

    void on_clientConnected();

    void on_clientDisconnected();

    void on_clientStateChanged(QAbstractSocket::SocketState state);

    void on_clientReadyRead();

    void on_actStartListen_triggered();

    void on_actStopListen_triggered();

    void on_actClearText_triggered();

    void on_btnSend_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QHostInfo>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    labListen = new QLabel("监听状态:");
    labListen->setMinimumWidth(200);
    labSocketState = new QLabel("Socket状态:");
    labSocketState->setMinimumWidth(200);
    ui->statusBar->addWidget(labListen);
    ui->statusBar->addWidget(labSocketState);

    setWindowTitle("服务器:" + getLocalIP());

    tcpServer = new QTcpServer(this);

    connect(tcpServer, SIGNAL(newConnection()),
            this, SLOT(on_newConnection()));


}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(tcpServer->isListening())
    {
        tcpServer->close();
    }
    event->accept();
}

QString MainWindow::getLocalIP()
{
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString loaclIP;
    QList<QHostAddress> addList = hostInfo.addresses();
    foreach (auto aHost, addList)
    {
        if(aHost.protocol() == QAbstractSocket::IPv4Protocol)
        {
            if(loaclIP.isEmpty())
            {
                loaclIP = aHost.toString();
            }
            ui->comboBoxAddresses->addItem(aHost.toString());
        }
    }
    return loaclIP;
}

void MainWindow::on_newConnection()
{
    tcpSocket = tcpServer->nextPendingConnection(); //获取socket
    connect(tcpSocket, SIGNAL(connected()), this, SLOT(on_clientConnected()));
    on_clientConnected(); //当前状态已经发送,需要直接调用通知
    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(on_clientDisconnected()));
    connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(on_clientStateChanged(QAbstractSocket::SocketState)));
    on_clientStateChanged(tcpSocket->state()); //当前状态已经发送,需要直接调用通知

    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(on_clientReadyRead()));

}

void MainWindow::on_clientConnected()
{
    ui->plainTextEdit->appendPlainText("**client socket connected");
    ui->plainTextEdit->appendPlainText("**peer address: " + tcpSocket->peerAddress().toString());
    ui->plainTextEdit->appendPlainText("**peer port " + QString::number(tcpSocket->peerPort()));
}

void MainWindow::on_clientDisconnected()
{
    ui->plainTextEdit->appendPlainText("**client socket disconnected");
    tcpSocket->deleteLater();
}

void MainWindow::on_clientStateChanged(QAbstractSocket::SocketState state)
{
    switch (state)
    {
    case QAbstractSocket::UnconnectedState:
        labSocketState->setText("socket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        labSocketState->setText("socket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        labSocketState->setText("socket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        labSocketState->setText("socket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        labSocketState->setText("socket状态:BoundState");
        break;
    case QAbstractSocket::ListeningState:
        labSocketState->setText("socket状态:ListeningState");
        break;
    case QAbstractSocket::ClosingState:
        labSocketState->setText("socket状态:ClosingState");
        break;
    default:
        break;
    }
}

void MainWindow::on_clientReadyRead()
{
    //    while(tcpSocket->canReadLine())
    int nLen = 0;
    do
    {
        char data[1024] = {0};
        nLen = tcpSocket->readLine(data, 1023);
        if(nLen > 0)
        {
            ui->plainTextEdit->appendPlainText(QString::asprintf("[in]: %s", data));
        }
    } while(nLen > 0);
}

void MainWindow::on_actStartListen_triggered()
{
    QString IP = ui->comboBoxAddresses->currentText();
    int port = ui->spinBoxPort->value();

    QHostAddress addr(IP);
    tcpServer->listen(addr, port);

    ui->plainTextEdit->appendPlainText("**开始监听");
    ui->plainTextEdit->appendPlainText("**服务IP:" + tcpServer->serverAddress().toString());
    ui->plainTextEdit->appendPlainText("**服务器端口:" + QString::number(tcpServer->serverPort()));

    ui->actStartListen->setEnabled(false);
    ui->actStopListen->setEnabled(true);
    labListen->setText("监听状态:开始");
}

void MainWindow::on_actStopListen_triggered()
{
    if(tcpServer->isListening())
    {
        tcpServer->close();
        ui->actStartListen->setEnabled(true);
        ui->actStopListen->setEnabled(false);
        labListen->setText("监听状态:停止");
    }
}

void MainWindow::on_actClearText_triggered()
{
    ui->plainTextEdit->clear();
}

void MainWindow::on_btnSend_clicked()
{
    QString msg = ui->lineEdit->text();
    ui->plainTextEdit->appendPlainText("[out] " + msg);
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    msg += "\n";
    QByteArray data = msg.toUtf8();

    tcpSocket->write(data);
}

3、实现客户端程序

在这里插入图片描述

(1)创建项目

(2)添加图标资源

在这里插入图片描述

(3)实现功能

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMainWindow>
#include <QTcpSocket>
#include <QLabel>


namespace Ui
{
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QLabel *labSocketState;

    QTcpSocket *tcpSocket;

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    QString getLocalIP();

private slots:
    void on_Connected();

    void on_Disconnected();

    void on_StateChanged(QAbstractSocket::SocketState state);

    void on_ReadyRead();

    void on_btnSend_clicked();

    void on_actConnect_triggered();

    void on_actDisconnect_triggered();

    void on_actClear_triggered();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QHostInfo>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    labSocketState = new QLabel("Socket状态:");
    labSocketState->setMinimumWidth(200);
    ui->statusBar->addWidget(labSocketState);

    setWindowTitle("客户端:" + getLocalIP());

    tcpSocket = new QTcpSocket;
    connect(tcpSocket, SIGNAL(connected()), this, SLOT(on_Connected()));
    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(on_Disconnected()));
    connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(on_StateChanged(QAbstractSocket::SocketState)));
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(on_ReadyRead()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

QString MainWindow::getLocalIP()
{
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString loaclIP;
    QList<QHostAddress> addList = hostInfo.addresses();
    foreach (auto aHost, addList)
    {
        if(aHost.protocol() == QAbstractSocket::IPv4Protocol)
        {
            if(loaclIP.isEmpty())
            {
                loaclIP = aHost.toString();
            }
            ui->comboBox->addItem(aHost.toString());
        }
    }
    return loaclIP;
}

void MainWindow::on_Connected()
{
    ui->plainTextEdit->appendPlainText("**socket connected");
    ui->plainTextEdit->appendPlainText("**peer address: " + tcpSocket->peerAddress().toString());
    ui->plainTextEdit->appendPlainText("**peer port " + QString::number(tcpSocket->peerPort()));
}

void MainWindow::on_Disconnected()
{
    ui->plainTextEdit->appendPlainText("**socket disconnected");
}

void MainWindow::on_StateChanged(QAbstractSocket::SocketState state)
{
    switch (state)
    {
    case QAbstractSocket::UnconnectedState:
        labSocketState->setText("socket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        labSocketState->setText("socket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        labSocketState->setText("socket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        labSocketState->setText("socket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        labSocketState->setText("socket状态:BoundState");
        break;
    case QAbstractSocket::ListeningState:
        labSocketState->setText("socket状态:ListeningState");
        break;
    case QAbstractSocket::ClosingState:
        labSocketState->setText("socket状态:ClosingState");
        break;
    default:
        break;
    }
}

void MainWindow::on_ReadyRead()
{
    int nLen = 0;
    do
    {
        char data[1024] = {0};
        nLen = tcpSocket->readLine(data, 1023);
        if(nLen > 0)
        {
            ui->plainTextEdit->appendPlainText(QString::asprintf("[in]: %s", data));
        }
    } while(nLen > 0);
}

void MainWindow::on_btnSend_clicked()
{
    QString msg = ui->lineEdit->text();
    ui->plainTextEdit->appendPlainText("[out] " + msg);
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    msg += "\n";
    QByteArray data = msg.toUtf8();

    tcpSocket->write(data);
}

void MainWindow::on_actConnect_triggered()
{
    QString IP = ui->comboBox->currentText();
    int port = ui->spinBox->value();
    tcpSocket->connectToHost(IP, port);

    ui->actConnect->setEnabled(false);
    ui->actDisconnect->setEnabled(true);
}

void MainWindow::on_actDisconnect_triggered()
{
    if(tcpSocket->state() == QAbstractSocket::ConnectedState)
    {
        tcpSocket->disconnectFromHost();
    }

    ui->actConnect->setEnabled(true);
    ui->actDisconnect->setEnabled(false);
}

void MainWindow::on_actClear_triggered()
{
    ui->plainTextEdit->clear();
}

在这里插入图片描述

三、UDP通信

UDP用户数据报协议,是轻量的、不可靠的、面向数据报、无连接的协议。

1、实现单播/广播程序

在这里插入图片描述

(1)创建项目

(2)添加图标资源

在这里插入图片描述

(3)实现功能

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QHostInfo>

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();
    setWindowTitle("Udp收发器:" + localIP);

    udpSocket = new QUdpSocket(this);
    connect(udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(on_StateChanged(QAbstractSocket::SocketState)));
    connect(udpSocket, SIGNAL(readyRead()),
            this, SLOT(on_SocketReadyRead()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

QString MainWindow::getLocalIP()
{
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString loaclIP;
    QList<QHostAddress> addList = hostInfo.addresses();
    foreach (auto aHost, addList)
    {
        if(aHost.protocol() == QAbstractSocket::IPv4Protocol)
        {
            if(loaclIP.isEmpty())
            {
                loaclIP = aHost.toString();
            }
            ui->comboBox->addItem(aHost.toString());
        }
    }
    return loaclIP;
}

void MainWindow::on_StateChanged(QAbstractSocket::SocketState state)
{
    switch (state)
    {
    case QAbstractSocket::UnconnectedState:
        labSocketState->setText("socket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        labSocketState->setText("socket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        labSocketState->setText("socket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        labSocketState->setText("socket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        labSocketState->setText("socket状态:BoundState");
        break;
    case QAbstractSocket::ListeningState:
        labSocketState->setText("socket状态:ListeningState");
        break;
    case QAbstractSocket::ClosingState:
        labSocketState->setText("socket状态:ClosingState");
        break;
    default:
        break;
    }
}

void MainWindow::on_SocketReadyRead()
{
    QByteArray datagram;
    datagram.resize(udpSocket->pendingDatagramSize());
    QHostAddress peerAddr;
    unsigned short peerPort;

    udpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort);

    QString str = datagram.data();
    QString peer = "[From " + peerAddr.toString() + ":" + QString::asprintf("%d", peerPort) + "] ";
    ui->plainTextEdit->appendPlainText(peer  + str);
}

void MainWindow::on_actStart_triggered()
{
    quint16 port = ui->spinBoxBindPort->value();
    if(udpSocket->bind(port))
    {
        ui->plainTextEdit->appendPlainText("**已绑定成功");
        ui->plainTextEdit->appendPlainText("**端口:" + QString::number(udpSocket->localPort()));

        ui->actStart->setEnabled(false);
        ui->actStop->setEnabled(true);
    }
}

void MainWindow::on_actStop_triggered()
{
    udpSocket->abort();
    ui->actStart->setEnabled(true);
    ui->actStop->setEnabled(false);
    ui->plainTextEdit->appendPlainText("**已解除绑定");
}

void MainWindow::on_actClear_triggered()
{
    ui->plainTextEdit->clear();
}

void MainWindow::on_pushButton_clicked()
{
    // 单播
    QString targetIP = ui->comboBox->currentText();
    quint16 targetPort = ui->spinBoxPort->value();
    QHostAddress targetAddr(targetIP);

    QString msg = ui->lineEdit->text();
    QByteArray data = msg.toUtf8();

    udpSocket->writeDatagram(data, targetAddr, targetPort);
    ui->plainTextEdit->appendPlainText("[out] " + msg);

    ui->lineEdit->clear();
    ui->lineEdit->setFocus();
}

void MainWindow::on_pushButton_2_clicked()
{
    // 广播
    quint16 targetPort = ui->spinBoxPort->value();

    QString msg = ui->lineEdit->text();
    QByteArray data = msg.toUtf8();

    udpSocket->writeDatagram(data, QHostAddress::Broadcast, targetPort);
    ui->plainTextEdit->appendPlainText("[out] " + msg);

    ui->lineEdit->clear();
    ui->lineEdit->setFocus();
}

在这里插入图片描述

2、实现组播程序

在这里插入图片描述

(1)拷贝上一个项目

(2)修改控件

在这里插入图片描述

(3)实现功能

#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();
    setWindowTitle("Udp组播收发器:" + localIP);

    udpSocket = new QUdpSocket(this);
    connect(udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this, SLOT(on_StateChanged(QAbstractSocket::SocketState)));
    connect(udpSocket, SIGNAL(readyRead()),
            this, SLOT(on_SocketReadyRead()));

}

MainWindow::~MainWindow()
{
    delete ui;
}

QString MainWindow::getLocalIP()
{
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString loaclIP;
    QList<QHostAddress> addList = hostInfo.addresses();
    foreach (auto aHost, addList)
    {
        if(aHost.protocol() == QAbstractSocket::IPv4Protocol)
        {
            if(loaclIP.isEmpty())
            {
                loaclIP = aHost.toString();
            }
            ui->comboBox->addItem(aHost.toString());
        }
    }
    return loaclIP;
}

void MainWindow::on_StateChanged(QAbstractSocket::SocketState state)
{
    switch (state)
    {
    case QAbstractSocket::UnconnectedState:
        labSocketState->setText("socket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        labSocketState->setText("socket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        labSocketState->setText("socket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        labSocketState->setText("socket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        labSocketState->setText("socket状态:BoundState");
        break;
    case QAbstractSocket::ListeningState:
        labSocketState->setText("socket状态:ListeningState");
        break;
    case QAbstractSocket::ClosingState:
        labSocketState->setText("socket状态:ClosingState");
        break;
    default:
        break;
    }
}

void MainWindow::on_SocketReadyRead()
{
    QByteArray datagram;
    datagram.resize(udpSocket->pendingDatagramSize());
    QHostAddress peerAddr;
    unsigned short peerPort;

    udpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort);

    QString str = datagram.data();
    QString peer = "[From " + peerAddr.toString() + ":" + QString::asprintf("%d", peerPort) + "] ";
    ui->plainTextEdit->appendPlainText(peer  + str);
}

void MainWindow::on_actStart_triggered()
{
    QString IP = ui->comboBox->currentText();
    groupAddress = QHostAddress(IP);

    quint16 groupPort = ui->spinBoxBindPort->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->actStart->setEnabled(false);
        ui->actStop->setEnabled(true);
        ui->comboBox->setEnabled(false);
    }
    else
    {
        ui->plainTextEdit->appendPlainText("**端口绑定失败");
    }
}

void MainWindow::on_actStop_triggered()
{
    udpSocket->leaveMulticastGroup(groupAddress);

    udpSocket->abort();
    ui->actStart->setEnabled(true);
    ui->actStop->setEnabled(false);
    ui->comboBox->setEnabled(true);
    ui->plainTextEdit->appendPlainText("**已退出组播,解除端口绑定");
}

void MainWindow::on_actClear_triggered()
{
    ui->plainTextEdit->clear();
}

void MainWindow::on_btnSend_clicked()
{
    QString targetIP = ui->comboBox->currentText();
    quint16 targetPort = ui->spinBoxBindPort->value();
    QHostAddress targetAddr(targetIP);

    QString msg = ui->lineEdit->text();
    QByteArray data = msg.toUtf8();

    udpSocket->writeDatagram(data, targetAddr, targetPort);
    ui->plainTextEdit->appendPlainText("[out] " + msg);

    ui->lineEdit->clear();
    ui->lineEdit->setFocus();
}

在这里插入图片描述

四、HTTP通信

1、相关类

QNetworkRequest,通过一个URL地址发起网络请求,也保存网络请求信息。
QNetworkAccessManager,用于协调网络操作,在QNetworkRequest发起一个网络请求后,负责发送网络请求,创建网络响应。
QNwtworkReply,网络请求的响应。

1、实现基于http协议文件下载

在这里插入图片描述

(1)创建项目

在这里插入图片描述

(2)实现功能

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

#include <QDesktopServices>
void MainWindow::on_finished()
{
    QFileInfo fileInfo;
    fileInfo.setFile(downloadFile->fileName());
    downloadFile->close();
    delete downloadFile;
    downloadFile = nullptr;
    reply->deleteLater();
    reply = nullptr;

    if(ui->checkBox->isChecked())
    {
        QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absolutePath()));
        ui->btnDownload->setEnabled(true);
    }
}

void MainWindow::on_readyRead()
{
    downloadFile->write(reply->readAll());
}

void MainWindow::on_downloadProgress(qint64 readBytes, qint64 totalBytes)
{
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(readBytes);
}


void MainWindow::on_btnDownload_clicked()
{
    QString strUrl = ui->lineEditUrl->text();
    if(strUrl.isEmpty())
    {
        QMessageBox::information(this, "error", "请输入正确地址");
        return;
    }

    QUrl newUrl = QUrl::fromUserInput(strUrl);
    if(!newUrl.isValid())
    {
        QMessageBox::information(this, "error",
                                 QString::asprintf("无效的URL:%s\n错误信息: %s", strUrl.data(), newUrl.errorString().data()));
        return;
    }

    QString tempDir = ui->lineEditSavePath->text();
    if(tempDir.isEmpty())
    {
        QMessageBox::information(this, "error", "保存路径无效");
        return;
    }

    QString fullFileName = tempDir + newUrl.fileName();
    if(QFile::exists(fullFileName))
    {
        QFile::remove(fullFileName);
    }

    downloadFile = new QFile(fullFileName);
    if(!downloadFile->open(QIODevice::WriteOnly))
    {
        QMessageBox::information(this, "error", "文件打开失败:" + fullFileName);
        return;
    }

    ui->btnDownload->setEnabled(false);
    reply = networkManager.get(QNetworkRequest(newUrl));
    connect(reply, SIGNAL(finished()), this, SLOT(on_finished()));
    connect(reply, SIGNAL(readyRead()), this, SLOT(on_readyRead()));
    connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(on_downloadProgress(qint64, qint64)));
}

void MainWindow::on_btnDefaultPath_clicked()
{
    QString curPath = QDir::currentPath();
    QDir dir(curPath);
    QString sub("temp");
    dir.mkdir(sub);
    ui->lineEditSavePath->setText(dir.path() + "/" + sub + "/");
}

在这里插入图片描述

五、打包程序

将指定程序打包,将依赖库打包进目录
D:\Qt\Qt5.13.0\5.13.0\mingw73_64\bin\windeployqt.exe E:/XXX/xxx.exe

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/422366.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java中几种常见的创建线程的方式

创建线程的几种方式 方法解释Thread()创建线程对象Thread(String name)创建线程对象&#xff0c;并给线程命名&#xff0c;不会影响线程Thread(Runnable runnable)使用Runnable对象创建线程Thread(Runnable runnable, String name)使用Runnable对象创建线程并给线程命名 方式…

直流电压变送器更改从站地址

直流电压变送器采集模块转RS485修改地址 产品图片 产品说明书 修改从站地址 在串口助手上将默认的从站地址01h修改为0Bh 原从站地址&#xff1a;01h 修改参数&#xff1a;10h 通信参数允许修改寄存器&#xff1a;1b fe&#xff08;说明书里7166的十六进制&#xff09; 00 02…

buuctf misc做题笔记

喵喵喵 使用stegsolve.jar&#xff0c;按BGR顺序提取出一个png图片&#xff0c;是一个只显示一半的二维码&#xff0c;修改图片高度显示全部二维码&#xff0c;解析出一个百度网盘地址&#xff0c;https://pan.baidu.com/s/1pLT2J4f 下载得到压缩包flag.rar。解压成功&#xf…

Vue开发实例(二)Vue代码运行及分析配置

Vue项目代码运行及分析 一、项目运行二、目录结构说明1、项目本身结构2、其他可能用到的文件夹 三、建议配置1、启动服务浏览器自动打开页面地址2、关闭eslint校验工具3、 src文件夹的别名的设置 一、项目运行 上篇文件末尾介绍到&#xff0c;进入项目&#xff0c;运行启动命令…

7.WEB渗透测试-Linux基础知识-Linux基础操作(一)

内容参考于&#xff1a; 易锦网校会员专享课 上一篇内容&#xff1a;5.WEB渗透测试-前置基础知识-常用的dos命令-CSDN博客 1.终端 终端&#xff1a;是一种特殊的字符设备&#xff0c;用来向计算机输入数据和显示计算机的输出 2.相对路径、绝对路径 绝对路径&#xff1a;cd/h…

怎么把人物从图中抠出?分享几种好用的抠图方法

在日常生活中&#xff0c;我们时常需要将人物从繁杂的背景中优雅地提取出来&#xff0c;无论是为了制作一张精美的证件照&#xff0c;还是为了设计一幅引人注目的海报或宣传画。然而&#xff0c;对于许多非专业人士来说&#xff0c;这仿佛是一场与细节的捉迷藏游戏&#xff0c;…

Web Tomcat

目录 1 前言2 Tomcat的安装3 Tomcat文件的构成4 Tomcat的使用步骤 1 前言 Tomcat是一个 http(web)的容器&#xff0c;笼统的理解一下所有的网站都叫做web。这个web容器可以把我们的前端(htmlcssjs)和后端(servlet)代码都运行起来。 Tomcat是一个免费的开源的Servlet容器&#…

鸿蒙Harmony应用开发—ArkTS声明式开发(触摸事件)

当手指在组件上按下、滑动、抬起时触发。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 onTouch onTouch(event: (event: TouchEvent) > void) 手指触摸动作触发该回调。 卡片能力&#xff1a; 从…

STM32标准库开发——PWR电源控制

PWR简介 STM32内部供电方案 从图中可以看出VDD供电区域中有个电压调节器&#xff0c;可以降压到1.8V给CPU内部一些比较重要的设备供电&#xff0c;STM32内部不都是3.3V供电。另外还有低电压检测器&#xff0c;能够自动判断当前电压是否满足供电要求以此来灵活调节VBAT的供电电源…

13-Linux部署Kafka集群

Linux部署Kafka集群 简介 Kafka是一款分布式的、去中心化的、高吞吐低延迟、订阅模式的消息队列系统。 同RabbitMQ一样&#xff0c;Kafka也是消息队列。不过RabbitMQ多用于后端系统&#xff0c;因其更加专注于消息的延迟和容错。 Kafka多用于大数据体系&#xff0c;因其更加…

整数和浮点数在内存中的存储(大小端字节序,浮点数的存取)

目录 1.整数在内存中的存储 2.大小端字节序和字节序判断 2.1什么是大小端&#xff1f; 2.2为什么会有大小端 3.浮点数在内存中的存储 3.1浮点数的存储 3.1.1 浮点数存的过程 3.1.2 浮点数取的过程 3.2 解析 3.3 验证浮点数的存储方式 1.整数在内存中的存储 整数的二进…

Tomcat 部署和优化 (一)---------安装Oracle jdk 、tomcat

自 2017 年 11 月编程语言排行榜 Java 占比 13%&#xff0c;高居榜首&#xff0c;Tomcat 也一度成为 Java开发人员的首选。其开源、占用系统资源少、跨平台等特性被深受喜爱。本章主要学习如何部署 Tomcat 服务&#xff0c;根据生产环境实现多个虚拟主机的配置&#xff0c;最后…

『京墨』1.7.0 发布,开源的诗文(名句)、歇后语、成语、绕口令、节日等的阅读 APP

1.7.0 更新日志 优化 UI 显示&#xff1b;优化数据同步&#xff0c;尤其是诗文同步&#xff1b;【诗文名句】【成语】【歇后语】模块添加收藏功能&#xff1b;添加“滑动翻页”功能。 介绍 『京墨』开源的古诗词文&#xff08;名句&#xff09;、歇后语、成语、绕口令、节日…

C++/WinRT教程(第三篇)API的使用

目录 前言 Windows API 在WinRT中的投影 C/WinRT的头文件&#xff08;投影标头&#xff09; 通过对象、接口或通过 ABI 访问成员 投影类型的初始化方法 不要错误地使用延迟初始化 不要错误地使用复制构造 使用 winrt::make 进行构造 标准构造方法 在WinRT组件中实现A…

【Word如何在表格和标题中间插入一行】

目的&#xff1a;主要是为了满足文件设计需求&#xff0c;标题前面要空出一行 操作步骤&#xff1a; 1、将鼠标光标停在标题行的最前方&#xff0c;点击回车&#xff0c;就会在表格和标题中间插入一行空白标题行。 2、因为空白标题行会影响目录的生成&#xff0c;所以将空白行…

基于springboot+vue的实验室管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

对象的组合(java)

组合与复用 Circle类创建圆对象 Circle类创建圆锥对象&#xff0c;Circle类将Circle类声明的对象作为自己的一个成员 圆锥通过调用方法将某个圆的引用传递给圆锥的Circle类型的成员变量 package Absent;public class Chapter3 {public static void main(String[] args) {// …

jupyter 用pyecharts进行数据分析

一、jupyter和pyecharts下载和打开 因为我是用的pycharm&#xff0c;所以我直接在pycharm项目终端中下载pip install jupyter,pip install pyecharts 在你下载的项目路径中输入jupyter notebook 之后会进入页面 Jupyter 具体使用参考这个链接&#xff1a;Jupyter Notebook基本…

基于tomcat的JavaWeb实现

Tomcat服务器 免费&#xff0c;性能一般的服务器 安装配置 基于Java&#xff0c;故需要配置环境变量&#xff0c;新加系统路径JAVA_HOME&#xff0c;路径为jdk的主目录。 而后打开bin目录下的startup.bat文件出现如下窗口说明配置成功 idea继承tomcat服务器 使用java开发…

HCIA-Datacom实验指导手册:7 构建简单 IPv6 网络

HCIA-Datacom实验指导手册&#xff1a;7 构建简单 IPv6 网络 一、实验介绍&#xff1a;二、实验拓扑&#xff1a;三、实验目的&#xff1a;四、配置步骤&#xff1a;步骤 1 设备基础配置设备命名 步骤 2 配置设备及接口 IPv6 功能步骤 3 配置接口的 link-local 地址&#xff0c…