Qt网络编程-写一个简单的网络调试助手

news2024/9/23 7:30:52

环境

Windows:Qt5.15.2(VS2022)

Linux:Qt5.12.12(gcc)

源代码

TCP服务器

头文件:

#ifndef TCPSERVERWIDGET_H
#define TCPSERVERWIDGET_H
#include <QWidget>
namespace Ui {
class TCPServerWidget;
}
class QTcpServer;
class QTcpSocket;
class TCPServerWidget : public QWidget {
    Q_OBJECT
public:
    explicit TCPServerWidget(QWidget *parent = nullptr);
    ~TCPServerWidget();

private:
    QTcpSocket *socket(int row);
private slots:
    void on_listen_clicked();
    void on_close_clicked();
    void on_send_clicked();
    void on_clear_clicked();

private:
    Ui::TCPServerWidget *ui;
    QTcpServer *m_Server;
    QList<QTcpSocket *> m_Clients;
};
#endif // TCPSERVERWIDGET_H

源文件:

#include "tcpserverwidget.h"
#include "common.h"
#include "ui_tcpserverwidget.h"
#include <QHeaderView>
#include <QTcpServer>
#include <QTcpSocket>
TCPServerWidget::TCPServerWidget(QWidget *parent)
    : QWidget(parent), ui(new Ui::TCPServerWidget) {
    ui->setupUi(this);
    ui->localIp->addItem("Any");
    ui->localIp->addItems(getIPAddresses());
    ui->clientTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->clientTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->clientTable->horizontalHeader()->setSectionResizeMode(
        QHeaderView::Stretch);
    m_Server = new QTcpServer;
    connect(m_Server, &QTcpServer::newConnection, [=]() {
        QTcpSocket *tcpSocket = m_Server->nextPendingConnection();
        QString ip = tcpSocket->peerAddress().toString();
        quint16 port = tcpSocket->peerPort();
        appendLog(ui->textEdit, QString("%1:%2:connect").arg(ip).arg(port));
        bool r = false;
        for (int i = 0; i < ui->clientTable->rowCount(); ++i) {
            QTableWidgetItem *ipitem = ui->clientTable->item(i, 0);
            QTableWidgetItem *portitem = ui->clientTable->item(i, 1);
            if (nullptr != ipitem && nullptr != portitem &&
                ipitem->text() == ip && portitem->text().toUShort() == port) {
                r = true;
                break;
            }
        }
        connect(tcpSocket, &QTcpSocket::disconnected, [=]() {
            appendLog(ui->textEdit,
                      QString("%1:%2 disconnected")
                          .arg(tcpSocket->peerAddress().toString())
                          .arg(tcpSocket->peerPort()));
            for (int i = 0; i < ui->clientTable->rowCount(); ++i) {
                QTableWidgetItem *ipitem = ui->clientTable->item(i, 0);
                QTableWidgetItem *portitem = ui->clientTable->item(i, 1);
                if (nullptr != ipitem && nullptr != portitem &&
                    ipitem->text() == ip &&
                    portitem->text().toUShort() == port) {
                    ui->clientTable->removeRow(i);
                    break;
                }
            }
            for (QTcpSocket *socket : m_Clients) {
                if (ip == socket->peerAddress().toString() &&
                    port == socket->peerPort()) {
                    m_Clients.removeOne(socket);
                    socket = nullptr;
                    break;
                }
            }
        });
        connect(tcpSocket, &QTcpSocket::readyRead, [=]() {
            QByteArray data = (ui->toHex->isChecked())
                ? tcpSocket->readAll().toHex()
                : tcpSocket->readAll();
            appendLog(ui->textEdit,
                      QString("%1:%2:%3").arg(ip).arg(port).arg(QString(data)));
        });
        m_Clients.append(tcpSocket);
        int row = ui->clientTable->rowCount();
        ui->clientTable->insertRow(row);
        ui->clientTable->setItem(row, 0, new QTableWidgetItem(ip));
        ui->clientTable->setItem(row, 1,
                                 new QTableWidgetItem(QString::number(port)));
    });
}

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

QTcpSocket *TCPServerWidget::socket(int row) {
    QTableWidgetItem *ipitem = ui->clientTable->item(row, 0);
    QTableWidgetItem *portitem = ui->clientTable->item(row, 1);
    if (nullptr != ipitem && nullptr != portitem) {
        QString ip = ipitem->text();
        quint16 port = portitem->text().toUShort();
        for (QTcpSocket *tcpSocket : m_Clients) {
            if (ip == tcpSocket->peerAddress().toString() &&
                port == tcpSocket->peerPort())
                return tcpSocket;
        }
    }
    return nullptr;
}

void TCPServerWidget::on_listen_clicked() {

    if (ui->listen->text() == "listen") {
        if (m_Server->listen((ui->localIp->currentText() == "Any")
                                 ? QHostAddress::Any
                                 : QHostAddress(ui->localIp->currentText()),
                             ui->localPort->value())) {
            ui->listen->setText("listening");
            appendLog(ui->textEdit, "start listening");
        } else {
            appendLog(ui->textEdit,
                      "start listen error:" + m_Server->errorString());
        }
    } else {
        m_Server->close();
        ui->listen->setText("listen");
        for (QTcpSocket *tcpSocket : m_Clients) {
            tcpSocket->close();
            tcpSocket->disconnectFromHost();
        }
        m_Clients.clear();
        appendLog(ui->textEdit, "stop listening");
    }
}

void TCPServerWidget::on_close_clicked() {
    int row = ui->clientTable->currentRow();
    QTcpSocket *tcpSocket = socket(row);
    if (nullptr != tcpSocket) {
        tcpSocket->close();
        tcpSocket->disconnectFromHost();
    }
}

void TCPServerWidget::on_send_clicked() {
    QByteArray data = (ui->toHex->isChecked())
        ? QByteArray::fromHex(ui->message->text().toUtf8())
        : ui->message->text().toUtf8();
    int row = ui->clientTable->currentRow();
    QTcpSocket *tcpSocket = socket(row);
    if (nullptr != tcpSocket)tcpSocket->write(data, data.size());
}

void TCPServerWidget::on_clear_clicked() {
    ui->textEdit->clear();
}

TCP客户端

头文件:

#ifndef TCPCLIENTWIDGET_H
#define TCPCLIENTWIDGET_H

#include <QWidget>

namespace Ui {
class TCPClientWidget;
}

class QTcpSocket;
class TCPClientWidget : public QWidget {
    Q_OBJECT

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

private slots:
    void on_connect_clicked();

    void on_send_clicked();

    void on_clear_clicked();

private:
    Ui::TCPClientWidget *ui;
    QTcpSocket *m_Socket;
};

#endif // TCPCLIENTWIDGET_H

源文件:

#include "tcpclientwidget.h"
#include "common.h"
#include "ui_tcpclientwidget.h"
#include <QFutureWatcher>
#include <QTcpSocket>
#include <QtConcurrent/QtConcurrent>

TCPClientWidget::TCPClientWidget(QWidget *parent)
    : QWidget(parent), ui(new Ui::TCPClientWidget) {
    ui->setupUi(this);
    ui->localIp->addItems(getIPAddresses());
    m_Socket = new QTcpSocket;
    connect(m_Socket, &QTcpSocket::disconnected, [=]() {
        ui->connect->setText("connect");
        appendLog(ui->textEdit, "disconnect");
    });
    connect(m_Socket, &QTcpSocket::readyRead, [=]() {
        QByteArray data = (ui->toHex->isChecked()) ? m_Socket->readAll().toHex()
                                                   : m_Socket->readAll();
        appendLog(ui->textEdit, QString(data));
    });
}

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

void TCPClientWidget::on_connect_clicked() {
    if ("connect" == ui->connect->text()) {
        if (ui->bind->isChecked()) {
            if (!m_Socket->bind(QHostAddress(ui->localIp->currentText()),
                                ui->localPort->value())) {
                appendLog(ui->textEdit,
                          "bind error:" + m_Socket->errorString());
                return;
            }
        }
        ui->connect->setEnabled(false);
        m_Socket->connectToHost(QHostAddress(ui->serverIp->text()),
                                ui->serverPort->value());
        if (m_Socket->waitForConnected()) {
            ui->connect->setText("disconnect");

            appendLog(ui->textEdit, "connect");
        } else
            appendLog(ui->textEdit, "connect error:" + m_Socket->errorString());
        ui->connect->setEnabled(true);
    } else {
        m_Socket->close();
        m_Socket->disconnectFromHost();
        ui->connect->setText("connect");
        appendLog(ui->textEdit, "disconnect");
    }
}

void TCPClientWidget::on_send_clicked() {
    QByteArray data = (ui->toHex->isChecked())
        ? QByteArray::fromHex(ui->message->text().toUtf8())
        : ui->message->text().toUtf8();
    if (m_Socket->isOpen()) m_Socket->write(data, data.size());
}

void TCPClientWidget::on_clear_clicked() {
    ui->textEdit->clear();
}

UDP

头文件:

#ifndef UDPWIDGET_H
#define UDPWIDGET_H

#include <QWidget>

namespace Ui {
class UDPWidget;
}

class QUdpSocket;
class UDPWidget : public QWidget {
  Q_OBJECT

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

 private slots:
  void on_bind_clicked();

  void on_send_2_clicked();

  void on_clear_2_clicked();

 private:
  Ui::UDPWidget *ui;
  QUdpSocket *m_Socket;
};

#endif  // UDPWIDGET_H

源文件:

#include "udpwidget.h"
#include <QUdpSocket>
#include "common.h"
#include "ui_udpwidget.h"

UDPWidget::UDPWidget(QWidget *parent) : QWidget(parent), ui(new Ui::UDPWidget) {
  ui->setupUi(this);
  ui->localIp_2->addItems(getIPAddresses());
  m_Socket = new QUdpSocket;
  connect(m_Socket, &QUdpSocket::readyRead, [=]() {
    while (m_Socket->hasPendingDatagrams()) {
      QByteArray data;
      QHostAddress host;
      quint16 port;
      data.resize(m_Socket->pendingDatagramSize());
      m_Socket->readDatagram(data.data(), data.size(), &host, &port);
      data = (ui->toHex_2->isChecked()) ? data.toHex() : data;
      appendLog(ui->textEdit, QString("%1:%2:%3")
                                  .arg(host.toString())
                                  .arg(port)
                                  .arg(QString(data)));
    }
  });
}

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

void UDPWidget::on_bind_clicked() {
  if (ui->bind->text() == "bind") {
    if (m_Socket->bind(QHostAddress(ui->localIp_2->currentText()),
                       ui->localPort_2->value()))
      ui->bind->setText("unbind");
    else
      appendLog(ui->textEdit, "bind error:" + m_Socket->errorString());
  } else {
    m_Socket->abort();
    ui->bind->setText("bind");
  }
}

void UDPWidget::on_send_2_clicked() {
  QByteArray data = (ui->toHex_2->isChecked())
                        ? QByteArray::fromHex(ui->message_2->text().toUtf8())
                        : ui->message_2->text().toUtf8();
  m_Socket->writeDatagram(data, QHostAddress(ui->serverIp->text()),
                          ui->serverPort->value());
}

void UDPWidget::on_clear_2_clicked() { ui->textEdit->clear(); }

运行效果

TCP服务器与多个客户端通信:

UDP之间通信:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java学习17-- super类

重点&#xff1a;super类 & 方法重写 super类 super指的是本级的上一级&#xff0c;即father class父类 很好理解&#xff0c;比如Person class>Student class 当前在Student class执行&#xff0c;那么就写this.xxx 需要在Student程序里面调用Person&#xff0c;那就…

L3HCTF 2024

Check in 输入一个1就获得flag

打印斐波那契数列

定义&#xff1a; 斐波那契数列是指这样一个数列&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34&#xff0c;55&#xff0c;89……这个数列从第3项开始 &#xff0c;每一项都等于前两项之和。 …

【复现】九思OA系统 SQL注入漏洞_43

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 九思软件自主研发的iThink协同OA办公自动化系统是面向中高端企业、政府机关和事业单位、等大型企业的协同办公软件&#xff0c;面…

QLabel重绘实现圆角矩形图片/文本和图片同时显示

QLabel一般用于显示一段文字&#xff0c;这段文字可以被鼠标选中/复制&#xff0c;也可是设置自动换行等&#xff0c;还可以用于显示图片。 但是使用QLabel显示图片时&#xff0c;qss样式设置的圆角radius属性是不生效的。 QLabel显示纯文本时&#xff0c;设置了背景颜色后&a…

Vue3.0(五):Vue-Router 4.x详解

Vue-Router详解 vue-router教程 认识前端路由 路由实际上是网络工程中的一个术语 在架构一个网络的时候&#xff0c;常用到两个很重要的设备—路由器和交换机路由器实际上就是分配ip地址&#xff0c;并且维护着ip地址与电脑mac地址的映射关系通过映射关系&#xff0c;路由器…

【Godot4.2】文件系统自定义控件 - GroupButtons

GroupButtons 概述 读者朋友们好&#xff0c;我是巽星石&#xff0c;这是我的Godot4.2文件系统自定义控件系列文章。 在很多程序或插件设计中&#xff0c;都会用到一堆按钮的形式&#xff0c;好处是比较直观&#xff0c;用啥点啥&#xff0c;本质上相当于一个简化的二级树形…

【Git版本控制 01】基本操作

目录 一、初始配置 二、添加文件 三、查看日志 四、修改文件 五、版本回退 六、撤销修改 七、删除文件 一、初始配置 Git版本控制器&#xff1a;记录每次的修改以及版本迭代的一个管理系统。 # 初始化本地仓库&#xff1a;git init(base) [rootlocalhost gitcode]# gi…

【通讯录案例-偏好设置 Objective-C语言】

一、刚才,我们plist存储,讲完了,这个plist,我直接,右键,打开 打开 不用xcode,我就用文本文档打开,打开方式:其他 选择:文本编辑 打开 好,这个里边儿啊,就是我们刚才存的一个Key:Value 它本质上,是一个xml 这是一种文件的格式, 等你们讲到网络的时候,实际上,…

Android 环境搭建

1、桥接工具安装 网站地址&#xff1a;AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 使用安装包&#xff1a; adb 查看当前链接成功的设备&#xff1a;adb devices 使用adb shell指令来进入到手机的后台&#xff1a;

Ondo宣布将其原生稳定币USDY带入Sui生态

重要提示&#xff1a;USDY是由短期美国国债支持的token化票据&#xff0c;持有者享受稳定币的实用性同时获得收益。USDY不得在美国或向美国人出售或以其他方式提供。USDY也未根据1933年美国证券法注册。 不到一年的时间&#xff0c;Sui已经成为全链TVL排名前十的区块链&#xf…

MySQL- 运维-分库分表-Mycat

一、Mycat概述 1、安装 2、概念介绍 二、Mycat入门 启动服务 三、Mycat配置 1、schema.xml 2、rule.xml 3、server.xml 四、Mycat分片 1、垂直分库 2、水平分表 五、Mycat管理及监控 1、Mycat原理 2、Mycat管理工具 &#xff08;1&#xff09;、命令行 &#xff08;2&#…

SpringBoot + Tess4J 实现本地与远程图片的文字识别

1 前言 1.1 概要 在本文中&#xff0c;我们将探讨如何在Spring Boot应用程序里集成Tess4J来实现OCR&#xff08;光学字符识别&#xff09;&#xff0c;以识别出本地和远程图片中的文字。 我们将从添加依赖说起&#xff0c;然后创建服务类以实现OCR&#xff0c;最后展示如何处…

基于微信小程序的新生报到系统的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

如何给闲置电脑安装黑群晖

准备 diskgenius &#xff0c;黑群晖引导文件&#xff08;有些需要扩展驱动包&#xff09;&#xff0c;如果给U盘安装需要balenaEtcher或者rufus&#xff08;U盘安装还需要ChipGenus&#xff09;&#xff0c;如果给硬盘安装需要有pe推荐firePE或U启通 我以U盘为例 首先去找这…

【RPA】浅谈RPA技术及其应用

摘要&#xff1a;随着信息技术的飞速发展&#xff0c;企业对于自动化、智能化的需求日益增强。RPA&#xff08;Robotic Process Automation&#xff0c;机器人流程自动化&#xff09;技术应运而生&#xff0c;为企业提供了全新的自动化解决方案。本文首先介绍了RPA技术的基本概…

Stability AI一种新型随心所欲生成不同音调、口音、语气的文本到语音(TTS)音频模型

该模型无需提前录制人声样本作为参考&#xff0c;仅凭文字描述就能生成所需的声音特征。用户只需描述他们想要的声音特点&#xff0c;例如“一个语速较快、带有英国口音的女声”&#xff0c;模型即可相应地生成符合要求的语音。它不仅能模仿已有的声音&#xff0c;还能根据用户…

ESP8266 tcpsocket透传模式流程介绍

一、整体流程介绍 二、固件介绍 固件视频演示地址&#xff1a; ESP8266-配网&热点设置说明_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1hq4y127dN/?spm_id_from333.999.0.0

第三百一十五回

文章目录 1. 概念介绍2. 基本用法3. 补充用法4. 内容总结 我们在上一章回中介绍了"再谈ListView中的分隔线"&#xff0c;本章回中将介绍showMenu的用法.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在第一百六十三回中介绍了showMenu相关的内容…

Log4j2漏洞(二)3种方式复现反弹shell

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、前言 明天就是除夕了&#xff0c;提前祝大家&#x…