QT网络调试助手

QT网络调试助手

  •  1.开发流程
  •  2.QTtcp服务器
    •    1.1 服务端数据读取
    •    1.2 服务端发送数据-所有客户端
    •    1.3 服务端自动刷新ip地址
    •    1.4 服务端检测客户端断开状态
    •    1.5 服务端发送数据-指定特定客户端发送数据
    •    1.6 服务端停止监听和断开
  •  3.QTtcp客户端

 1.开发流程

在这里插入图片描述

 2.QTtcp服务器

	1.添加网络访问权限
	 QT += network
	2.创建一个新对象
    server = new QTcpServer(this);
    3.当监听按钮按下后开始监听
void Widget::on_btnListen_clicked()
{
    //2.监听:bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)   8888-15000
    //QHostAddress addr("192.168.0.101");
    port = ui->lineEditPort->text().toUInt();
    if(!server->listen(QHostAddress(ui->comboBoxAddr->currentText()),port)){    //自动检测ip地址:QHostAddress::Any
        QMessageBox msgBox;
        msgBox.setWindowTitle("监听失败");
        msgBox.setText("端口号被占用");
        msgBox.exec();
        return;
    }
    ui->btnListen->setEnabled(false);
    ui->btnLineOut->setEnabled(true);
    ui->btnStopListen->setEnabled(true);
    ui->btnSend->setEnabled(true);
    //qDebug() << QHostAddress(ui->comboBoxAddr->currentText());
}
	4.监听到新的newConnection()信号后对新的连接进行处理
	connect(server,SIGNAL(newConnection()),this,SLOT(on_newClient_connect()));
	
void Widget::on_newClient_connect()
{
    //所有的数据操作都是TcpSocket进行
    //bool QTcpServer::hasPendingConnections() const    有新的连接返回True
    if(server->hasPendingConnections()){
        //QTcpSocket *QTcpServer::nextPendingConnection()   返回下个连接来的connect
        QTcpSocket *connection = server->nextPendingConnection(); //获得到的客户端连接信息都在connection里,并将信息也保存在server中
        qDebug() << "client addr: " <<connection->peerAddress().toString() <<",port: " << connection->peerPort();
        ui->textEditRev->insertPlainText("客户端地址:" + connection->peerAddress().toString()+
                                         "\n客户端端口号:" + QString::number(connection->peerPort())+ "\n");

        connect(connection,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler()));

        //断开后信号:void QAbstractSocket::disconnected()
        //connect(connection,SIGNAL(disconnected()),this,SLOT(mdisconnected()));

        //void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)


        connect(connection,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
                this,SLOT(mstateChanged(QAbstractSocket::SocketState)));

        ui->comboBoxChildren->addItem(QString::number(connection->peerPort()));
        ui->comboBoxChildren->setCurrentText(QString::number(connection->peerPort()));
        if(!ui->btnSend->isEnabled()){
            ui->btnSend->setEnabled(true);
        }
    }
}

   1.1 服务端数据读取

	connect(connection,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler())void Widget::on_readyRead_handler()
{
    QTcpSocket *tmpSocket = qobject_cast<QTcpSocket *>(sender());  //获得信号的发出者
    QByteArray RevData = tmpSocket->readAll();
    ui->textEditRev->insertPlainText("客户端:" + RevData + '\n');
    ui->textEditRev->moveCursor(QTextCursor::End);  //将读取光标移动至尾部
    ui->textEditRev->ensureCursorVisible(); //确定光标可见
}

   1.2 服务端发送数据-所有客户端

on_newClient_connect()中
	QTcpSocket *connection = server->nextPendingConnection(); 会将信息也保存在server中,server是全局变量,对server来说,每一个socket都是server的child
	所以通过其父类QObject的FindChildren可以找到所有的socket
}

void Widget::on_btnSend_clicked()
{
    //QTcpSocket *connection = server->nextPendingConnection(); //获得到的客户端连接信息都在connection里,并将信息也保存在server中
    QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();
    for(QTcpSocket *tmp : tcpSocketClients){
        //ui->textEditSend->toPlainText().toStdString().c_str()--先将QString转换成标准的c++字符串,再转换成const char*型
        tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());
    }
}

   1.3 服务端自动刷新ip地址

	QNetworkInterface
	QList<QHostAddress> QNetworkInterface::allAddresses()

    //QList<QHostAddress> QNetworkInterface::allAddresses()
    QList<QHostAddress> address = QNetworkInterface::allAddresses();    //获取地址
    for(QHostAddress tmp : address){
        if(tmp.protocol() == QAbstractSocket::IPv4Protocol) //将ipv4的地址刷入combox
            ui->comboBoxAddr->addItem(tmp.toString());
    }

   1.4 服务端检测客户端断开状态

注:每次一断开之后必须清空通道即deleteLater();
	否则server中会一直保留该通道
	1.信号:void QAbstractSocket::disconnected()	
	connect(connection,SIGNAL(disconnected()),this,SLOT(mdisconnected()));
	void Widget::mdisconnected()
{
    QTcpSocket *tmpSocket = qobject_cast<QTcpSocket *>(sender());  //获得信号的发出者
    qDebug() << "client Out";
    ui->textEditRev->insertPlainText("客户端断开! ");
    tmpSocket->deleteLater();

}

	2.信号:void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)
	void Widget::mstateChanged(QAbstractSocket::SocketState socketState)
{
    QTcpSocket *tmpSocket = qobject_cast<QTcpSocket *>(sender());  //获得信号的发出者
    switch(socketState){
    case QAbstractSocket::ClosingState:
        //case QAbstractSocket::UnconnectedState:
        ui->textEditRev->insertPlainText("客户端断开! ");
        tmpSocket->deleteLater();
        break;
    }
}

   1.5 服务端发送数据-指定特定客户端发送数据

	1.因为ComboBox不提供鼠标点击刷新事件,因此需要重写ComboBox的鼠标点击事件和信号
	void MyComboBox::mousePressEvent(QMouseEvent *e)
{
    if(e->button() == Qt::LeftButton){
        emit ComboBox_clicked();
    }
    QComboBox::mousePressEvent(e);
}
	2.将控件提升为MyComboBox,并绑定信号与槽
	connect(ui->comboBoxChildren,&MyComboBox::ComboBox_clicked,this,&Widget::MyComboBox_refresh);
	//刷新ComboBox控件内容---为ComboBox添加接入的端口
	void Widget::MyComboBox_refresh()
{
    ui->comboBoxChildren->clear();
    QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();
    for(QTcpSocket *tmp : tcpSocketClients){
        ui->comboBoxChildren->addItem(QString::number(tmp->peerPort()));
    }
    ui->comboBoxChildren->addItem("all");
}
	2.重写发送
void Widget::on_btnSend_clicked()
{
    //QTcpSocket *connection = server->nextPendingConnection(); //获得到的客户端连接信息都在connection里,并将信息也保存在server中
    QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();
    if(tcpSocketClients.isEmpty()){
        QMessageBox msg;
        msg.setText("当前无连接");
        msg.exec();
        ui->btnSend->setEnabled(false);
        return ;
    }


    if(ui->comboBoxChildren->currentText() != "all"){
        QString currentname = ui->comboBoxChildren->currentText();
        for(QTcpSocket *tmp :tcpSocketClients){
            if(QString::number(tmp->peerPort()) == currentname){
                tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());
            }

        }
    }else{
        for(QTcpSocket *tmp : tcpSocketClients){
            //ui->textEditSend->toPlainText().toStdString().c_str()--先将QString转换成标准的c++字符串,再转换成const char*型
            tmp->write(ui->textEditSend->toPlainText().toStdString().c_str());
        }
    }
}


   1.6 服务端停止监听和断开

void Widget::on_btnStopListen_clicked()
{
    QList<QTcpSocket *> tcpSocketClients = server->findChildren<QTcpSocket *>();
    for(QTcpSocket *tmp : tcpSocketClients){
        tmp->close();
    }
    server->close();
    ui->btnListen->setEnabled(true);
    ui->btnLineOut->setEnabled(false);
    ui->btnStopListen->setEnabled(false);
}

void Widget::on_btnLineOut_clicked()
{
    on_btnStopListen_clicked();
    delete server;
    this->close();
}

 3.QTtcp客户端

	客户端逻辑相对简单直接上代码:
void Widget::on_pushButtonConnect_clicked()
{
    //void connectToHost(const QHostAddress &address, quint16 port, QIODevice::OpenMode openMode = ReadWrite)
    client->connectToHost(ui->lineEditIp->text(),ui->lineEditPort->text().toUInt());	//连接服务器


    timer = new QTimer(this);
    timer->setSingleShot(1);
    timer->setInterval(5000);
    connect(timer,SIGNAL(timeout()),this,SLOT(onTimerOut()));



    connect(client,SIGNAL(connected()),this,SLOT(onConnected()));

    //void QAbstractSocket::error(QAbstractSocket::SocketError socketError)
    connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(onError(QAbstractSocket::SocketError)));

    this->setEnabled(false);
    timer->start();
}

void Widget::mread_data_from_server()
{
    setInsertColor(Qt::black, "服务器:"+ client->readAll());
}

void Widget::on_btnSend_clicked()
{
    QByteArray sendData = ui->textEditSend->toPlainText().toStdString().c_str();
    client->write(sendData);
    setInsertColor(Qt::red,"客户端:" + sendData);
}

void Widget::on_pushButtonOut_clicked()
{
    client->close();
    ui->textEditRev->append("断开连接\n");
    ui->pushButtonConnect->setEnabled(true);
    ui->lineEditIp->setEnabled(true);
    ui->lineEditPort->setEnabled(true);
    ui->pushButtonOut->setEnabled(false);
    ui->btnSend->setEnabled(false);
}

void Widget::onConnected()
{
    timer->stop();
    this->setEnabled(true);
    ui->textEditRev->insertPlainText("连接成功\n");
    ui->pushButtonConnect->setEnabled(false);
    ui->lineEditIp->setEnabled(false);
    ui->lineEditPort->setEnabled(false);
    ui->pushButtonOut->setEnabled(true);
    ui->btnSend->setEnabled(true);
}

void Widget::onError(QAbstractSocket::SocketError error)
{
    this->setEnabled(true);
    on_pushButtonOut_clicked();
}

void Widget::onTimerOut()
{
    ui->textEditRev->insertPlainText("连接超时!");
    client->abort(); //放弃当前连接
    this->setEnabled(true);


}

void Widget::setInsertColor(Qt::GlobalColor color, QString str)
{
    QTextCursor cursor = ui->textEditRev->textCursor();
    QTextCharFormat format;
    QBrush brush(color);
    format.setForeground(brush);
    cursor.setCharFormat(format);
    cursor.insertText(str+'\n');
    ui->textEditRev->moveCursor(QTextCursor::End);  //将光标移动至尾部
    ui->textEditRev->ensureCursorVisible(); //确定光标可见
}

链接:https://pan.baidu.com/s/1uI_bhvufjcuW1R6CrR9P7g
提取码:3urt
–来自百度网盘超级会员V5的分享

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

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

相关文章

深挖苹果Find My技术,伦茨科技ST17H6x芯片赋予产品功能

苹果发布AirTag发布以来&#xff0c;大家都更加注重物品的防丢&#xff0c;苹果的 Find My 就可以查找 iPhone、Mac、AirPods、Apple Watch&#xff0c;如今的Find My已经不单单可以查找苹果的设备&#xff0c;随着第三方设备的加入&#xff0c;将丰富Find My Network的版图。产…

15 个最佳遥感软件

无论您是专业地理学家、地球科学专业的学生&#xff0c;还是只是一个好奇的爱好者&#xff0c;都有各种各样的遥感软件可以帮助您完成工作。从对详细航空图像进行分类到创建复杂的 3D 模型&#xff0c;这 15 个遥感软件包都是最好的。让我们逐一介绍给您: 1.ERDAS Imagine ERD…

遵循苹果商店政策:确保Flutter应用在上架过程中合规操作

引言 Flutter是一款由Google推出的跨平台移动应用开发框架&#xff0c;其强大的性能和流畅的用户体验使其备受开发者青睐。然而&#xff0c;开发一款应用只是第一步&#xff0c;将其成功上架到苹果商店才是实现商业目标的关键一步。本文将详细介绍如何使用Flutter将应用程序上…

数据治理10大坑

✅作者简介&#xff1a;《数据运营&#xff1a;数据分析模型撬动新零售实战》作者、《数据实践之美》作者、数据科技公司创始人、多次参加国家级大数据行业标准研讨及制定、高端企培合作讲师。 &#x1f338;公众号&#xff1a;风姑娘的数字视角&#xff0c;免费分享数据应用相…

使用ARCore深度API实现点云采集

一、深度API 本小节内容摘自ARCore官方文档。 ARCore 深度API Depth API 可助力实现对象遮挡、提升沉浸感和新颖的互动体验&#xff0c;从而增强 AR 体验的真实感。 在下图中&#xff0c;右侧画面是采用深度API进行遮挡后的效果&#xff0c;与左侧图相比更加真实。 深度值 给…

Vue项目引入字体文件无效

这是原来的&#xff0c;没有生效 font-face {font-family: BebasNeue;src: url(./font/BebasNeue.otf);font-weight: normal;font-style: normal; }这是修改后的&#xff08;多了个空格&#xff09; font-face {font-family: Bebas Neue;src: url(./font/BebasNeue.otf);font-…

stream使用

stream流式计算 在Java1.8之前还没有stream流式算法的时候&#xff0c;我们要是在一个放有多个User对象的list集合中&#xff0c;将每个User对象的主键ID取出&#xff0c;组合成一个新的集合&#xff0c;首先想到的肯定是遍历&#xff0c;如下&#xff1a; List<Long> u…

C++ Primer 总结索引 | 第十二章:动态内存

1、到目前为止&#xff0c;我们编写的程序中 所使用的对象 都有着严格定义的生存期。全局对象 在程序启动时分配&#xff0c;在程序结束时 销毁。对于 局部自动对象&#xff0c;当我们进入 其定义所在的程序块时被创建&#xff0c;在 离开块时销毁。局部static对象 在第一次使用…

前端JS商品规格组合

给定一个数组 let data [{name: "颜色",specs: ["白色", "黑色"],},{name: "尺寸",specs: ["14寸","15寸", "16寸"],},{name: "处理器",specs: ["i5", "i7", "i9&…

AI音乐GPT时刻来临:Suno 快速入门手册!

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

KnowLog:基于知识增强的日志预训练语言模型|顶会ICSE 2024论文

徐波 东华大学副教授 东华大学计算机学院信息技术系副系主任&#xff0c;复旦大学知识工场实验室副主任&#xff0c;智能运维方向负责人。入选“上海市青年科技英才扬帆计划”。研究成果发表在IJCAI、ICDE、ICSE、ISSRE、ICWS、CIKM、COLING等国际会议上&#xff0c;曾获中国数…

【威胁情报综述阅读3】Cyber Threat Intelligence Mining for Proactive Cybersecurity Defense

【威胁情报综述阅读1】Cyber Threat Intelligence Mining for Proactive Cybersecurity Defense: A Survey and New Perspectives 写在最前面一、介绍二、网络威胁情报挖掘方法和分类A. 研究方法1&#xff09; 第 1 步 - 网络场景分析&#xff1a;2&#xff09; 第 2 步 - 数据…

【Spring实战项目】SpringBoot3整合WebSocket+拦截器实现登录验证!从原理到实战

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

【快捷部署】013_Podman(3.4.4)

&#x1f4e3;【快捷部署系列】013期信息 编号选型版本操作系统部署形式部署模式复检时间013podman3.4.4Ubuntu 22.04apt-2024-04-03 一、快捷部署 注意! 必须满足&#xff1a;Ubuntu 20.10 and newer #由于本期安装脚本较为简单&#xff0c;所以不制作一键安装脚本&#xf…

JDK下载安装配置

一.JDK安装配置。 1.安装注意路径,其他直接下一步。 2.配置。 下接第4步. 代码复制: JAVA_HOME D:\Program Files\Java\jdk1.8.0_91 D:\Program Files\Java\jdk1.8.0_91\bin 3.验证(CMD)。 java javac java -version 二.下载 1.下载JDK1.5-1.9(所有版本)下载: https://www.…

YOLOV5 改进:更换主干网络为Resnet

1、前言 之前实现了yolov5更换主干网络为MobileNet和vgg网络 本章将继续将yolov5代码进行更改,通过引用官方实现的resnet网络,替换原有的yolov5主干网络 替换的效果如下: 2、resnet 网络结构 测试的代码为官方的resnet34 通过summary 打印的resnet网络结构如下 =======…

Flutter应用发布流程详解:从开发到上架一站式指南

引言 Flutter是一款由Google推出的跨平台移动应用开发框架&#xff0c;其强大的性能和流畅的用户体验使其备受开发者青睐。然而&#xff0c;开发一款应用只是第一步&#xff0c;将其成功上架到苹果商店才是实现商业目标的关键一步。本文将详细介绍如何使用Flutter将应用程序上…

IP地址如何修改?分享操作技巧

在互联网世界中&#xff0c;IP地址是每台计算机或网络设备的唯一标识&#xff0c;它决定了设备在网络中的位置以及与其他设备的通信方式。然而&#xff0c;有时出于特定需求&#xff0c;我们可能需要修改设备的IP地址。虎观代理将详细阐述如何修改IP地址&#xff0c;并探讨在修…

一文读懂匈奴历史

匈奴&#xff0c;一个曾经叱咤风云的游牧民族&#xff0c;在中国历史上留下了浓墨重彩的一笔。他们的崛起和衰落&#xff0c;不仅影响了中原王朝的兴衰更迭&#xff0c;也深刻地改变了中国北方的民族构成和文化面貌。 1、匈奴的起源 根据司马迁的《史记》记载&#xff0c;匈奴…

某眼实时票房接口获取

某眼实时票房接口获取 前言解决方案1.找到veri.js2.找到signKey所在位置3.分析它所处的这个函数的内容4.index参数的获取5.signKey参数的获取运行结果关键代码另一种思路票房接口:https://piaofang.maoyan.com/dashboard-ajax https://piaofang.maoyan.com/dashboard 实时票房…