Qt 网络编程实战

07-08 1124阅读

一.获取主机的网络信息

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

QHostInfo类

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

    QNetworkInterface类

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

      Qt 网络编程实战

      1. 源码如下
      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      #include 
      #include
      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
      #include
      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 addrlist = hostinformation.addresses();
          ui->textEdit->append("本机的IPV4地址如下:");
          if(!addrlist.isEmpty())
          {
              //for遍历输出
              for(int i=0;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 addrlist = hostinformation.addresses();
          ui->textEdit->append("本机的IPV6地址如下:");
          if(!addrlist.isEmpty())
          {
              //for遍历输出
              for(int i=0;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 addrlist = hostInfo.addresses();
          if(!addrlist.isEmpty())
          {
              for(int i=0;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信息如下:");
          QListaddrlist = QNetworkInterface::allAddresses();
          if(!addrlist.isEmpty())
          {
              for(int i=0;i
                  if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
                  {
                      ui-textEdit->append(addrlist[i].toString());
                  }
              }
          }
      }
      void MainWindow::GetNetWorkInfo()
      {
          //获取所有网卡的网络信息
          QListlist =QNetworkInterface::allInterfaces();
          for(int i=0;i
              QNetworkInterface interface = list[i];
              if(!interface.isValid())
              {
                  continue;
              }
              ui-textEdit->append("设备名称:"+interface.humanReadableName());
              ui->textEdit->append("硬件地址:"+interface.hardwareAddress());
              //一个网卡,可以有多个IP地址
              QList list2 = interface.addressEntries();
              for(int j=0; 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编程(服务器端实现)

      • 项目效果

        Qt 网络编程实战

      • 客户端(使用的是调试助手)

        Qt 网络编程实战

      • 项目源码

        #include "mainwindow.h"
        #include "ui_mainwindow.h"
        #include
        #include
        MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent)
            , ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
            InitUI();
        }
        MainWindow::~MainWindow()
        {
            delete ui;
        }
        void MainWindow::InitUI()
        {
            //加状态栏中添加控件
            label_first=new QLabel();
            label_second=new QLabel();
            label_third=new QLabel();
            label_four=new QLabel();
            label_first->setText("监听状态:");
            label_third->setText("套接字状态:");
            label_first->setMaximumWidth(80);
            label_third->setMaximumWidth(80);
            label_second->setMinimumWidth(100);
            label_four->setMinimumWidth(100);
            ui->statusbar->addWidget(label_first);
            ui->statusbar->addWidget(label_second);
            ui->statusbar->addWidget(label_third);
            ui->statusbar->addWidget(label_four);
            //fromName 返回指定主机的主机信息
            QHostInfo hostInfo = QHostInfo::fromName(QHostInfo::localHostName());
            QList addrlist = hostInfo.addresses();
            if(!addrlist.isEmpty())
            {
                for(int i=0;i
                    QHostAddress address = addrlist[i];
                    if(address.protocol()==QAbstractSocket::IPv4Protocol)
                    {
                        ui-comboBox->addItem(address.toString());
                    }
                }
            }
            //本机的环回网卡的IP 127.0.0.1
            //用来做网络测试的
            ui->comboBox->addItem("127.0.0.1");
            //处理tcp通信
            tcpserver=new QTcpServer(this);
            //发现新信号就触发onNewConnection
            connect(tcpserver,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
        
        }
        void MainWindow::on_actionListen_triggered()
        {
            QString ip =ui->comboBox->currentText();
            //unsigned short
            quint16 port = ui->spinBox->value();
            QHostAddress addr(ip);
            //开始监听
            tcpserver->listen(addr,port);
            label_second->setText("已开始监听");
            ui->textEdit->append("开始监听,等待客户端发起连接...");
            ui->textEdit->append("服务器地址:"+tcpserver->serverAddress().toString());
            ui->textEdit->append("服务器端口:"+QString::number(tcpserver->serverPort()));
            //更改控件
            ui->actionStop->setEnabled(true);
            ui->actionListen->setEnabled(false);
        }
        void MainWindow::on_actionStop_triggered()
        {
            //停止监听
            if(tcpserver->isListening())
            {
                tcpserver->close();
                ui->actionListen->setEnabled(true);
                ui->actionStop->setEnabled(false);
                label_second->setText("已停止监听");
            }
        }
        void MainWindow::on_actionClear_triggered()
        {
            label_second->clear();
            label_four->clear();
            ui->textEdit->clear();
        }
        void MainWindow::onNewConnection()
        {
            //一旦有新的连接
            //难以理解的概念:套接字,相当于客户端套接字,每当有客户端发起请求,服务器就会分配一个套接字
            //去接待
            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)));
            onSocketStateChanged(tcpsocket->state());//先更新一下状态
        }
        void MainWindow::onSocketReadyRead()
        {
            //有数据可读时
            while(tcpsocket->canReadLine())
            {
                ui->textEdit->append("[收到]"+tcpsocket->readLine());
            }
        }
        void MainWindow::onConnected()
        {
            //刚连入成功
            ui->textEdit->append("\n客户端请求已经接入!");
            //获取客户端的地址信息
            ui->textEdit->append("客户端地址:"+tcpsocket->peerAddress().toString());
            ui->textEdit->append("客户端端口号:"+QString::number(tcpsocket->peerPort()));
        
        }
        void MainWindow::onDisconnected()
        {
            ui->textEdit->append("\n客户端已断开连接");
            tcpsocket->deleteLater();//以后在删除,这样更安全
        }
        void MainWindow::onSocketStateChanged(QAbstractSocket::SocketState status)
        {
            /*
                UnconnectedState,
                HostLookupState,
                ConnectingState,
                ConnectedState,
                BoundState,
                ListeningState,
                ClosingState
             */
            //套接字状态发生变化
            switch(status)
            {
                case QAbstractSocket::UnconnectedState:
                label_four->setText("未连接");
                break;
                case QAbstractSocket::HostLookupState:
                label_four->setText("正在查找主机名");
                break;
                case QAbstractSocket::ConnectingState:
                label_four->setText("正在连接");
                break;
                case QAbstractSocket::ConnectedState:
                label_four->setText("已连接");
                break;
                case QAbstractSocket::BoundState:
                label_four->setText("已绑定到IP地址和端口号");
                break;
                case QAbstractSocket::ListeningState:
                label_four->setText("正在监听");
                break;
                case QAbstractSocket::ClosingState:
                label_four->setText("准备关闭");
                break;
            }
        }
        void MainWindow::on_pushButton_clicked()
        {
            //发送一行字符串
            QString msg = ui->lineEdit->text();
            //utf编码,QByteArray在功能上很像字符数组
            QByteArray str=msg.toUtf8();
            str.append('\n');
            //服务器向客户端发送数据
            tcpsocket->write(str);
        }
        void MainWindow::on_actionQuit_triggered()
        {
            close();
        }
        

        2. 客户端实现

        • 效果展示

          Qt 网络编程实战

        • 源码如下

          #include "mainwindow.h"
          #include "ui_mainwindow.h"
          MainWindow::MainWindow(QWidget *parent)
              : QMainWindow(parent)
              , ui(new Ui::MainWindow)
          {
              ui->setupUi(this);
              //创建了客户端的套接字对象
              tcpsocket=new QTcpSocket(this);
              //连接成功会触发的
              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)));
              ui->actionConnect->setEnabled(true);
              ui->actionDisconnect->setEnabled(false);
          }
          MainWindow::~MainWindow()
          {
              delete ui;
          }
          void MainWindow::onConnected()
          {
              //peerAddress对等地址
              //打印服务器的地址
              ui->plainTextEdit->appendPlainText("已连接到服务器!");
              ui->plainTextEdit->appendPlainText("---服务器地址:"+
                      tcpsocket->peerAddress().toString());
              ui->plainTextEdit->appendPlainText("---服务器端口:"+
                                                 QString::number(tcpsocket->peerPort()));
          }
          void MainWindow::onDisconnected()
          {
              ui->plainTextEdit->appendPlainText("服务器的连接已经断开");
              ui->actionConnect->setEnabled(true);
              ui->actionDisconnect->setEnabled(false);
          }
          void MainWindow::onSocketStateChanged(QAbstractSocket::SocketState status)
          {
              //这和服务器端的判断一样的
          }
          void MainWindow::onSocketReadyRead()
          {
              while(tcpsocket->canReadLine())
              {
                  ui->plainTextEdit->appendPlainText("[收到]"+tcpsocket->readLine());
              }
          }
          void MainWindow::on_actionConnect_triggered()
          {
              QString ip = ui->lineEditIP->text();
              quint16 port=ui->spinBoxPort->value();
              tcpsocket->connectToHost(ip,port);
          }
          void MainWindow::on_actionDisconnect_triggered()
          {
              if(tcpsocket->state()==QAbstractSocket::ConnectedState)
              {
                  //从主机那断开
                  tcpsocket->disconnectFromHost();
              }
          }
          void MainWindow::closeEvent(QCloseEvent *event)
          {
              if(tcpsocket->state()==QAbstractSocket::ConnectedState)
              {
                  //从主机那断开
                  tcpsocket->disconnectFromHost();
              }
              event->accept();//不调用这个窗口就不会关闭
              //event->ignore();这个窗口就不关闭
          }
          void MainWindow::on_actionClear_triggered()
          {
              ui->plainTextEdit->clear();
          }
          void MainWindow::on_actionQuit_triggered()
          {
              close();
          }
          void MainWindow::on_pushButton_clicked()
          {
              QString msg = ui->lineEditSend->text();
              QByteArray str=msg.toUtf8();
              str.append('\n');
              tcpsocket->write(str);
              ui->plainTextEdit->appendPlainText("[发送]"+msg);
              ui->lineEditSend->clear();
              ui->lineEditSend->setFocus();//设置光标聚焦
          }
          
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]