zoukankan      html  css  js  c++  java
  • Qt5 编写网络调试助手

    QT中可以通过TCP协议让服务器和客户端之间行通信。所以下面我就围绕服务器和客户端来写。

    这是我们写服务器和客户端的具体流程:

    A、服务器:      

             1.创建QTcpServer对象
             2.启动服务器(监听)调用成员方法listen(QHostAddress::Any,端口号)
             3.当有客户端链接时候会发送newConnection信号,触发槽函数接受链接(得到一个与客户端通信的套接字QTcpSocket)
             4.QTcpsocket发送数据用成员方法write,
             5.读数据当客户端有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据

    B、客户端  :  

            1.创建QTcpSocket对象
            2.链接服务器connectToHost(QHostAddress("ip"),端口号)
            3.QTcpsocket发送数据用成员方法write,
            4.读数据当对方有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据

    我们需要调用到的头文件有两个:

    #include <QTcpServer>  
    #include <QTcpSocket>

    我们先要在工程文件中加入network

    QT       += core gui network

    下面我们来看看服务器程序步骤:

    1、初始化服务器server对象

    mServer = new QTcpServer();

    2、启动监听服务器

      mServer->listen(QHostAddress::Any,9988);//9988为端口号

    3、当有客户端链接时候会发送newConnection信号,触发槽函数接受链接(得到一个与客户端通信的套接字QTcpSocket)

     connect(mServer,SIGNAL(newConnection()),this,SLOT(new_client()));
     mSocket = mServer->nextPendingConnection();//与客户端通信的套接字

    4、发送数据

     mSocket->write(msg.toUtf8());

    5、读数据当客户端有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据

     connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_client_data()));

    6、连接多个客户端

     //可以实现同时读取多个客户端发送过来的消息
     QTcpSocket *obj = (QTcpSocket*)sender();

    7、检测掉线

     connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis())); //检测掉线信号

    下面是服务器的实现的具体代码:

    复制代码
     1 #include "tcpserver.h"
     2 #include "ui_tcpserver.h"
     3 #include <QDebug>
     4 TcpServer::TcpServer(QWidget *parent) :
     5     QMainWindow(parent),
     6     ui(new Ui::TcpServer)
     7 {
     8     ui->setupUi(this);
     9     //初始化服务器server对象
    10     mServer = new QTcpServer();
    11     //关联客户端连接信号newConnection
    12     connect(mServer,SIGNAL(newConnection()),this,SLOT(new_client())); //连接客户端
    13     //启动服务器监听
    14     mServer->listen(QHostAddress::Any,9988);
    15 
    16 }
    17 
    18 TcpServer::~TcpServer()
    19 {
    20     delete ui;
    21 }
    22 
    23 void TcpServer::new_client()
    24 {
    25     qDebug()<<"新客户段连接";
    26     mSocket = mServer->nextPendingConnection();//与客户端通信的套接字
    27     //关联接收客户端数据信号readyRead信号(客户端有数据就会发readyRead信号)
    28     connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_client_data()));
    29     //检测掉线信号
    30     connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis()));
    31 
    32 }
    33 
    34 void TcpServer::read_client_data()
    35 {
    36     //可以实现同时读取多个客户端发送过来的消息
    37     QTcpSocket *obj = (QTcpSocket*)sender();
    38     QString msg = obj->readAll();
    39     qDebug()<<msg;
    40 }
    41 
    42 void TcpServer::client_dis()
    43 {
    44      QTcpSocket *obj = (QTcpSocket*)sender();//掉线对象
    45      qDebug()<<obj->peerAddress().toString();//打印出掉线对象的ip
    46 }
    复制代码

    说完服务器那我们继续来看看客户端是怎么实现的:

    1、创建QTcpSocket对象

     mSocket = new QTcpSocket();

    2、链接服务器connectToHost(QHostAddress("ip"),端口号),连接服务器ip和端口号

     mSocket->connectToHost(ui->ipEdit->text(),ui->portEdit->text().toInt()); //ui->ipEdit->text():ip,ui->portEdit->text().toInt():端口号

    3、发送数据

    //取发送信息编辑框内容
    QString msg = ui->sendEdit->toPlainText();
    mSocket->write(msg.toUtf8());//转编码

    4、检测链接成功信号关联槽函数

     connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));

    5、检测掉线信号

     connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis()));

    6、服务器和客户端关闭都可以使用close

     mSocket->close();

    这是客户端实现的具体代码

    复制代码
     1 #include "tcpclient.h"
     2 #include "ui_tcpclient.h"
     3 #include <QDebug>
     4 TcpClient::TcpClient(QWidget *parent) :
     5     QMainWindow(parent),
     6     ui(new Ui::TcpClient)
     7 {
     8     ui->setupUi(this);
     9     //初始化套接字对象
    10     mSocket = new QTcpSocket();
    11     //关联数据信号
    12     connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data()));
    13 
    14 }
    15 
    16 TcpClient::~TcpClient()
    17 {
    18     delete ui;
    19 }
    20 
    21 void TcpClient::read_data()
    22 {
    23     QString msg = mSocket->readAll();
    24     qDebug()<<msg;
    25 }
    26 
    27 void TcpClient::on_btn_connectServer_clicked()
    28 {
    29     //检测链接成功信号关联槽函数
    30     connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));
    31     //检测掉线信号
    32     connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis()));
    33     //连接服务器,设置ip和端口号
    34     mSocket->connectToHost(ui->ipEdit->text(),ui->portEdit->text().toInt());
    35 
    36 }
    37 
    38 void TcpClient::on_btn_send_clicked()
    39 {
    40     //取发送信息编辑框内容
    41     QString msg = ui->sendEdit->toPlainText();
    42     mSocket->write(msg.toUtf8());//转编码
    43 }
    44 
    45 void TcpClient::connect_suc()
    46 {
    47     ui->btn_connectServer->setEnabled(false);//如果连接成功则连接按钮不能按下
    48 }
    49 void TcpClient::client_dis()
    50 {
    51     ui->btn_connectServer->setEnabled(true);//如果连接没有成功则连接按钮还可以按下
    52 }
    复制代码

    这是服务器和客户端分开两个文件夹写的程序,在这里我也实现了服务器和客户端写在同一个文件中

    具体代码如下:

    头文件:tcpapp.h

    #ifndef TCPAPP_H
    #define TCPAPP_H
    
    #include <QMainWindow>
    #include <QTcpServer>
    #include <QTcpSocket>
    #include <QHostAddress>
    #include <QFile>
    #include <QTimer>
    #include <QMessageBox>
    namespace Ui {
    class TcpApp;
    }
    
    class TcpApp : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit TcpApp(QWidget *parent = 0);
        ~TcpApp();
    
    private slots:
        void on_severRB_clicked();//选择作为服务器
    
        void on_clientRB_clicked();//选择作为客户端
    
        void on_StartBt_clicked();//启动服务器或链接客户端
    
        void on_closeBt_clicked();//关闭服务器或断开客户端
    
        void on_onlineUserList_doubleClicked(const QModelIndex &index);//选择给哪个客户端发送数据
    
        void on_autoCB_clicked(bool checked);//选择自动发送还是手动发送
    
        void on_sendMsgBt_clicked();//发送信息
    
        //服务器
        void accept_connect();//与newconnection信号关联
        void recv_data(); //接收数据
    
         void auto_time_send();//定时器定时发送数据
    
         void client_disconnect();//关联掉线信号
         void connect_suc();//检测客户端连接成功信号
    
         void on_clearRcvBt_clicked();
    
         void on_clearSendBt_clicked();
    
    private:
        Ui::TcpApp *ui;
        QTimer *mTimer;//定时发送数据
        QTcpServer *mServer;
        QTcpSocket *mSocket;
        QVector<QTcpSocket*> clients; //存储所有在线客户端(容器)
    
        bool isServer;//标志位,true为服务器,false为客户端
    
        //保存接收和发送数据的字节数
        quint64 recvSize;
        quint64 sendSize;
    
        qint16 onNum;
        bool isCheckServer;//判断是否选择了服务器
        bool isCheckClient;//判断是否选择了客户端
    
    
    };
    
    #endif // TCPAPP_H

    源文件:tcpapp.cpp

    #include "tcpapp.h"
    #include "ui_tcpapp.h"
    
    TcpApp::TcpApp(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::TcpApp),
        onNum(0)
    {
        ui->setupUi(this);
        recvSize = 0;
        sendSize = 0;
        //初始化定时器
        mTimer = new QTimer();
        connect(mTimer,SIGNAL(timeout()),this,SLOT(auto_time_send()));
    }
    
    TcpApp::~TcpApp()
    {
        delete ui;
    }
    
    //与newconnection信号关联
    void TcpApp::accept_connect()
    {
        mSocket = mServer->nextPendingConnection(); //返回与客户端连接通信的套接字
    
        //关联接收数据信号
        connect(mSocket,SIGNAL(readyRead()),this,SLOT(recv_data()));
        //关联掉线信号
        connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_disconnect()));
    
        //上线用户添加到客户列表容器
        clients.append(mSocket);
        //把用户添加到界面列表中
        QString ip = mSocket->peerAddress().toString().remove("::ffff:");//去除客户端中多余的字符
        ui->onlineUserList->addItem(ip);
    
        //在线数量添加
        onNum++;
        ui->onlineUserCount->setText(QString::number(onNum));//显示在线数
    
    }
    
    //接收数据
    void  TcpApp::recv_data()
    {
          QTcpSocket *obj = (QTcpSocket*)sender();
          //获取发送数据端的IP
          QString ip = obj->peerAddress().toString();
          ip.remove("::ffff:");
          QString msg = obj->readAll();
          ui->receiveList->addItem(ip+":"+msg);//显示接收到的数据
          recvSize += msg.size();//统计接收到的数据的字节数
          ui->receiveNumLabel->setText(QString::number(recvSize));
    }
    
    void TcpApp::client_disconnect()
    {
        QTcpSocket *obj = (QTcpSocket*)sender();//获取掉线对象
        if(isServer)
        {
            int row = clients.indexOf(obj);//找到掉线对象的内容所在的行
            QListWidgetItem *item = ui->onlineUserList->takeItem(row);//从界面列表中去除找到的一行内容
            delete item;
            clients.remove(row);//从容器中删除对象
    
            //掉线时删除在线数量
            onNum--;
            ui->onlineUserCount->setText(QString::number(onNum));
        }
        else
        {
            ui->StartBt->setEnabled(true);//断开连接的时候重新启用开始按钮
        }
    }
    
    
    //客户端连接成功
    void TcpApp::connect_suc()
    {
        ui->StartBt->setEnabled(false);//连接成功则禁用开始按钮
    }
    //定时器定时发送数据
    void TcpApp::auto_time_send()
    {
        quint64 len = mSocket->write(ui->sendMsgEdit->toPlainText().toUtf8());
        if(len > 0)
        {
            sendSize += len;//统计发送的字节数
            ui->sendNumLabel->setText(QString::number(sendSize));//把发送的字节数显示到sendNumLabel上
    
        }
    }
    
    //选择作为服务器
    void TcpApp::on_severRB_clicked()
    {
        this->isCheckServer = true;
        this->isServer = true;
        //获取本地ip显示在IpEdit中
       ui->IpEdit->setText(QHostAddress(QHostAddress::LocalHost).toString());
       ui->IpEdit->setEnabled(false);//关闭ip输入编辑器
       this->isCheckClient = false;
    
    }
    
    //选择作为客户端
    void TcpApp::on_clientRB_clicked()
    {
        this->isCheckClient = true;
        this->isServer = false;
        ui->IpEdit->setEnabled(true);//打开ip输入编辑器
        this->isCheckServer = false;
    
    }
    
    //启动服务器或者链接服务器
    void TcpApp::on_StartBt_clicked()
    {
        if(isServer) //服务器
        {
            mServer = new QTcpServer();
            //关联新客户端链接信号
            connect(mServer,SIGNAL(newConnection()),this,SLOT(accept_connect()));
            mServer->listen(QHostAddress::Any,ui->PortEdit->text().toInt());//启动服务器监听
            ui->StartBt->setEnabled(false);//开始按钮禁用
        }
        if(isServer == false) //客户端
        {
            mSocket = new QTcpSocket();
            //检测链接成功信号
            connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));
            //设置服务器的 ip和端口号
            mSocket->connectToHost(ui->IpEdit->text(),ui->PortEdit->text().toInt());
    
    
            //关联接收数据信号
            connect(mSocket,SIGNAL(readyRead()),this,SLOT(recv_data()));
            //关联掉线信号
            connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_disconnect()));
        }
    
        if(isCheckServer == false && isCheckClient == false)//如果两个都没选择
        {
            QMessageBox::warning(this,"提示","请选择服务器或者客户端");
            ui->StartBt->setEnabled(true);
            return;
        }
    
        if(isCheckServer)//选择了服务器
        {
           if(ui->PortEdit->text().isEmpty() || ui->PortEdit->text() == "请输入端口号")
           {
               QMessageBox::warning(this,"提示","请输入端口号");
               ui->StartBt->setEnabled(true);
               return;
           }
        }
    
        if(isCheckClient)//选择了客户端
        {
            if(ui->IpEdit->text().isEmpty() || ui->IpEdit->text() == "请输入ip" || ui->IpEdit->text() == "请输入端口号")
            {
                QMessageBox::warning(this,"提示","请输入ip和端口号");
                ui->StartBt->setEnabled(true);
                return;
            }
        }
    
    }
    
    //关闭服务器或者断开
    void TcpApp::on_closeBt_clicked()
    {
        if(isServer)//服务器
        {
            for(int i=0;i<clients.count();i++)
            {
                 clients.at(i)->close();//关闭所有客户端
            }
    
            //关闭所有服务器之后开始按钮才能启用
            mServer->close();
            ui->StartBt->setEnabled(true);
        }
        else //客户端
        {
            mSocket->close();//关闭客户端
            ui->StartBt->setEnabled(true);//启用开始按钮
        }
    
    }
    
    //双击选择要发送的客户端
    void TcpApp::on_onlineUserList_doubleClicked(const QModelIndex &index)
    {
        mSocket = clients.at(index.row());
    
    }
    
    //自动发送数据
    void TcpApp::on_autoCB_clicked(bool checked)
    {
        if(checked)
    
        {
            if(ui->autoTimeEdit->text().toInt() <= 0)
            {
                QMessageBox::warning(this,"提示","请输入时间值ms");
                ui->autoCB->setChecked(false);//把按钮重新置于没选中的状态
                return;
            }
            mTimer->start(ui->autoTimeEdit->text().toInt());//启动定时器
        }
        else
        {
            mTimer->stop();//停止定时器
        }
    
    }
    
    //手动发送数据
    void TcpApp::on_sendMsgBt_clicked()
    {
        auto_time_send();
    
    }
    
    //清空接收区
    void TcpApp::on_clearRcvBt_clicked()
    {
        ui->receiveNumLabel->clear();
        this->recvSize = 0;
        ui->receiveNumLabel->setText(QString::number(recvSize));
    }
    
    //清空发送区
    void TcpApp::on_clearSendBt_clicked()
    {
        ui->sendNumLabel->clear();
        this->sendSize = 0;
        ui->sendNumLabel->setText(QString::number(sendSize));
    }

    界面文件tcpapp.ui如下图

     

    此外这里还使用到了容器,在这里讲讲容器的使用

    1、定义容器对象

    QVector<QTcpSocket*> clients; //存储所有在线客户端(容器)
      解释:QTcpSocke*  容器的类型
           clients  容器名

    2、往容器中添加成员

    //上线用户添加到客户列表容器
     clients.append(mSocket); 

    3、寻找某个成员在容器中位置

     int row = clients.indexOf(obj);//找到掉线对象的内容所在的行

    4、从容器中删除成员

      clients.remove(row);//从容器中删除成员
  • 相关阅读:
    Maidsafe-去中心化互联网白皮书
    The Top 20 Cybersecurity Startups To Watch In 2021 Based On Crunchbase
    Top 10 Blockchain Security and Smart Contract Audit Companies
    The 20 Best Cybersecurity Startups To Watch In 2020
    Blockchain In Cybersecurity: 11 Startups To Watch In 2019
    004-STM32+BC26丨260Y基本控制篇(阿里云物联网平台)-在阿里云物联网平台上一型一密动态注册设备(Android)
    涂鸦开发-单片机+涂鸦模组开发+OTA
    000-ESP32学习开发-ESP32烧录板使用说明
    03-STM32+Air724UG远程升级篇OTA(阿里云物联网平台)-STM32+Air724UG使用阿里云物联网平台OTA远程更新STM32程序
    03-STM32+Air724UG远程升级篇OTA(自建物联网平台)-STM32+Air724UG实现利用http/https远程更新STM32程序(TCP指令,单片机程序检查更新)
  • 原文地址:https://www.cnblogs.com/wt88/p/14657183.html
Copyright © 2011-2022 走看看