Qt 网络编程实战

发布于:2024-07-05 ⋅ 阅读:(18) ⋅ 点赞:(0)

一.获取主机的网络信息

  1. 需要添加network模块
QT   += core gui network
  1. 主要涉及的类分析

QHostInfo类

  • QHostInfo::localHostName() 获取本地的主机名
  • QHostInfo::fromName(const QString &) 获取指定主机的主机信息 addresses接口

QNetworkInterface类

  • QNetworkInterface::allAddresses() 网卡所有的IP地址
  1. 项目效果

在这里插入图片描述

  1. 源码如下
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QHostInfo>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:

    //获取主机名
    void GetHostName();

    //获取IPV4
    void GetIPV4();

    //获取IPV6
    void GetIPV6();

    //清除文本内容
    void Clear_Text();

    //获取指定域名的IP地址
    void Get_DefineHost();
    void lookedUp(QHostInfo hostInfo);

    //主机所有网卡IP地址
    void GetAlladdresses();

    //所有网卡的网络信息
    void GetNetWorkInfo();

private:
    void InitConnectSignals();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QHostInfo>
#include<QNetworkInterface>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("主机的网络信息");
    InitConnectSignals();
}

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

void MainWindow::GetHostName()
{
    //获取当前的主机名
    QString hostname = QHostInfo::localHostName();
    ui->textEdit->append("当前的主机名为:"+hostname);

}

void MainWindow::GetIPV4()
{
    //获取当前的主机名
    QString hostname = QHostInfo::localHostName();

    //获取指定主机的主机信息
    QHostInfo hostinformation = QHostInfo::fromName(hostname);

    //Returns the list of IP addresses associated with hostName().
    //This list may be empty.
    //返回与hostName()相关联的IP地址列表。
    //该列表可能为空。
    QList<QHostAddress> addrlist = hostinformation.addresses();
    ui->textEdit->append("本机的IPV4地址如下:");

    if(!addrlist.isEmpty())
    {
        //for遍历输出
        for(int i=0;i<addrlist.size();i++)
        {
            //protocol是协议的意思
            if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
            {
                ui->textEdit->append(addrlist[i].toString());
            }
        }
    }

}

void MainWindow::GetIPV6()
{
    //获取当前的主机名
    QString hostname = QHostInfo::localHostName();

    //获取指定主机的主机信息
    QHostInfo hostinformation = QHostInfo::fromName(hostname);

    //Returns the list of IP addresses associated with hostName().
    //This list may be empty.
    //返回与hostName()相关联的IP地址列表。
    //该列表可能为空。
    QList<QHostAddress> addrlist = hostinformation.addresses();
    ui->textEdit->append("本机的IPV6地址如下:");

    if(!addrlist.isEmpty())
    {
        //for遍历输出
        for(int i=0;i<addrlist.size();i++)
        {
            //protocol是协议的意思
            if(addrlist[i].protocol()==QAbstractSocket::IPv6Protocol)
            {
                ui->textEdit->append(addrlist[i].toString());
            }
        }
    }
}

void MainWindow::Clear_Text()
{
    ui->textEdit->clear();
}

void MainWindow::Get_DefineHost()
{
    //获取lineEdit上的域名
    QString hostName =ui->lineEdit->text();
    if(hostName.isEmpty())
    {
        return ;
    }

    //获取域名的IPV4信息
    /*
     查找与主机名name相关联的IP地址,并返回用于查找的ID。当查找结果准备好时,
将使用QHostInfo参数调用receiver中的slot或信号成员。然后可以检查QHostInfo对象以获得查找结果。
      */
    //lookupHost(const QString &name, QObject *context, Func1 slot)
    QHostInfo::lookupHost(hostName,this,SLOT(lookedUp(QHostInfo)));
}

void MainWindow::lookedUp(QHostInfo hostInfo)
{
    //当前的主机名
    QString hostName=hostInfo.hostName();
    ui->textEdit->append("当前域名为:"+hostName+" IPV4信息如下:");

    QList<QHostAddress> addrlist = hostInfo.addresses();

    if(!addrlist.isEmpty())
    {
        for(int i=0;i<addrlist.count();i++)
        {
            if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
            {
                ui->textEdit->append(addrlist[i].toString());
            }
        }
    }

    /*
      常见的错误
QObject::connect: Incompatible sender/receiver arguments
        QHostInfoResult::resultsReady(QHostInfo) --> MainWindow::lookedUp(QHostInfo&)

        信号和槽的参数不匹配

     */
}

void MainWindow::GetAlladdresses()
{
    //获取网卡的所有IP信息
    ui->textEdit->append("所有网卡的IPV4信息如下:");
    QList<QHostAddress>addrlist = QNetworkInterface::allAddresses();
    if(!addrlist.isEmpty())
    {
        for(int i=0;i<addrlist.count();i++)
        {
            if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
            {
                ui->textEdit->append(addrlist[i].toString());
            }
        }
    }

}

void MainWindow::GetNetWorkInfo()
{
    //获取所有网卡的网络信息
    QList<QNetworkInterface>list =QNetworkInterface::allInterfaces();

    for(int i=0;i<list.count();i++)
    {
        QNetworkInterface interface = list[i];
        if(!interface.isValid())
        {
            continue;
        }

        ui->textEdit->append("设备名称:"+interface.humanReadableName());
        ui->textEdit->append("硬件地址:"+interface.hardwareAddress());


        //一个网卡,可以有多个IP地址
        QList<QNetworkAddressEntry> list2 = interface.addressEntries();
        for(int j=0; j<list2.count(); j++)
        {
              QNetworkAddressEntry entry = list2[j];
              ui->textEdit->append("\tIP地址:" + entry.ip().toString());
              ui->textEdit->append("\t子网掩码:" + entry.netmask().toString());
              ui->textEdit->append("\t广播地址: " + entry.broadcast().toString() + "\n");

         }
    }

}

void MainWindow::InitConnectSignals()
{
    //void pressed();
    connect(ui->pushButton_HostName,SIGNAL(pressed()),this,SLOT(GetHostName()));

    connect(ui->pushButton_IPV4,SIGNAL(pressed()),this,SLOT(GetIPV4()));

    connect(ui->pushButton_IPV6,SIGNAL(pressed()),this,SLOT(GetIPV6()));

    connect(ui->pushButton_Clear,SIGNAL(pressed()),this,SLOT(Clear_Text()));

    connect(ui->pushButton_DefineHost,SIGNAL(pressed()),this,SLOT(Get_DefineHost()));

    connect(ui->pushButton_Alladdresses,SIGNAL(pressed()),this,SLOT(GetAlladdresses()));

    connect(ui->pushButton_Network,SIGNAL(pressed()),this,SLOT(GetNetWorkInfo()));
}

二.TCP编程

1. server编程

  • 项目效果
    在这里插入图片描述

  • 客户端
    在这里插入图片描述

  • 项目源码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QHostInfo>
#include<QTcpSocket>

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

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

void MainWindow:: InitUI()
{
    //先处理combox中的主机的IP信息,使用的是IPV4
    QString localHostName = QHostInfo::localHostName();

    QHostInfo hostInformation = QHostInfo::fromName(localHostName);

    //主机的IP地址
    QList<QHostAddress> addrlist = hostInformation.addresses();

    if(!addrlist.isEmpty())
    {
        for(int i=0;i<addrlist.count();i++)
        {
            if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
            {
                ui->comboBox->addItem(addrlist[i].toString());
            }
        }
    }

    //处理tcp通信
    tcpserver=new QTcpServer(this);

    //发现新信号就触发onNewConnection
    //每次有新的连接时,他的信号就会发出。
    connect(tcpserver,SIGNAL(newConnection()),this,SLOT(onNewConnection()));

}


void MainWindow:: onNewConnection()
{
    //创建新的连接时,就会触发这个函数
    //创建一个新的套接字来对客户端进行服务

    /*
将下一个挂起的连接作为已连接的QTcpSocket对象返回。
套接字是作为服务器的子节点创建的,这意味着当QTcpServer对象被销毁时,
它将被自动删除。在使用完对象后显式删除它仍然是一个好主意,以避免浪费内存。
如果在没有挂起连接的情况下调用此函数,则返回Nullptr

      */
   tcpsocket=tcpserver->nextPendingConnection();

   //连接成功会触发的
   connect(tcpsocket,SIGNAL(connected()),this,SLOT(onConnected()));


   //当有数据可以读的时候,我们就读数据,(使用信号槽)
   connect(tcpsocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));


   connect(tcpsocket,SIGNAL(disconnected()),this,SLOT(onDisconnected()));

   // void stateChanged(QAbstractSocket::SocketState);
   connect(tcpsocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
           this,SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));


}


void MainWindow::onConnected()
{
    //刚连入成功
    ui->plainTextEdit->appendPlainText("\n客户端请求已经接入!");

    //获取客户端的地址信息
    ui->plainTextEdit->appendPlainText("客户端地址:"+tcpsocket->peerAddress().toString());

    ui->plainTextEdit->appendPlainText("客户端端口号:"+QString::number(tcpsocket->peerPort()));
}

void MainWindow::onSocketReadyRead()
{
    //有数据可读时
    while(tcpsocket->canReadLine())
    {
        ui->plainTextEdit->appendPlainText("[收到]"+tcpsocket->readLine());
    }
}



void MainWindow::on_actionListen_triggered()
{
    //监听需要IP地址和端口号
    QString IP=ui->comboBox->currentText();
    QHostAddress addr(IP);

    quint16 port=ui->spinBox->value();

    //开始监听
    tcpserver->listen(addr,port);

    ui->plainTextEdit->appendPlainText("开始监听,等待客户端发起连接...");

    ui->plainTextEdit->appendPlainText("服务器地址:"+tcpserver->serverAddress().toString());
    ui->plainTextEdit->appendPlainText("服务器端口:"+QString::number(tcpserver->serverPort()));

    //更改控件
    ui->actionStop->setEnabled(true);
    ui->actionListen->setEnabled(false);
}