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

环境

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.mfbz.cn/a/379670.html

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

相关文章

单片机的省电模式及策略

目录 一、单片机省电的核心策略 二、单片机IO口的几种模式 三、单片机的掉电运行模式 &#xff08;1&#xff09; 浅谈cpu运行为什么会需要时钟&#xff1f; &#xff08;2&#xff09;STC15系列单片机内部可以配置时钟 &#xff08;3&#xff09;分频策略&#xff0c;降低…

ubuntu22.04 安装部署05:禁用默认显卡驱动

一、相关文章 ubuntu22.04安装部署03&#xff1a; 设置root密码-CSDN博客 《ubuntu22.04装部署01&#xff1a;禁用内核更新》 《ubuntu22.04装部署02&#xff1a;禁用显卡更新》 二、场景说明 Ubuntu22.04 默认显卡驱动&#xff0c;如果安装cuda&#xff0c;需要单独安装显…

什么是向量数据库?为什么向量数据库对LLM很重要?

由于我们目前生活在人工智能革命之中&#xff0c;重要的是要了解许多新应用程序都依赖于向量嵌入&#xff08;vector embedding&#xff09;。因此&#xff0c;有必要了解向量数据库以及它们对 LLM 的重要性。 我们首先定义向量嵌入。向量嵌入是一种携带语义信息的数据表示形式…

了解海外云手机的多种功能

随着社会的高度发展&#xff0c;海外云手机成为商家不可或缺的工具&#xff0c;为企业出海提供了便利的解决方案。然而&#xff0c;谈及海外云手机&#xff0c;很多人仍不了解其强大功能。究竟海外云手机有哪些功能&#xff0c;可以为我们做些什么呢&#xff1f; 由于国内电商竞…

树与二叉树---数据结构

树作为一种逻辑结构&#xff0c;同时也是一种分层结构&#xff0c;具有以下两个特点&#xff1a; 1&#xff09;树的根结点没有前驱&#xff0c;除根结点外的所有结点有 且只有一个前驱。 2&#xff09;树中所有结点可以有零个或多个后继。 树结点数据结构 满二叉树和完全二…

Vue3编写简单的App组件(二)

一、Vue3页面渲染基本流程 1、入口文件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><link rel"icon" href"/favicon.ico"><meta name"viewport" content"widthde…

PlantUML绘制UML图教程

UML&#xff08;Unified Modeling Language&#xff09;是一种通用的建模语言&#xff0c;广泛用于软件开发中对系统进行可视化建模。PlantUML是一款强大的工具&#xff0c;通过简单的文本描述&#xff0c;能够生成UML图&#xff0c;包括类图、时序图、用例图等。PlantUML是一款…

【前端web入门第四天】01 复合选择器与伪类选择器

文章目录: 1. 复合选择器 1.1 后代选择器 1.2 子代选择器 1.3 并集选择器1.4 交集选择器(了解) 2.伪类选择器 2.1 伪类-文本2.2 伪类-超链接&#xff08;拓展) 1. 复合选择器 什么叫复合选择器? 由两个或多个基础选择器&#xff0c;通过不同的方式组合而成。 复合选择器的作…

Python中使用opencv-python库进行颜色检测

Python中使用opencv-python库进行颜色检测 之前写过一篇VC中使用OpenCV进行颜色检测的博文&#xff0c;当然使用opencv-python库也可以实现。 在Python中使用opencv-python库进行颜色检测非常简单&#xff0c;首选读取一张彩色图像&#xff0c;并调用函数imgHSV cv2.cvtColor…

从REPR设计模式看 .NET的新生代类库FastEndpoints的威力

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !序言 又到了一年年末,春节将至…

Android SDK 上传 Maven 喂奶级教程

最近领导给安排了个任务&#xff0c;让我把我们现有的一个 SDK 上传到 Maven 上去&#xff0c;方便客户直接用 gradle 依赖&#xff0c;不再需要拷贝 jar 和 so 了&#xff0c;此前我也看过一些相关的文章我想问题也不大&#xff0c;觉得工作量也就一两天的事情&#xff0c;主要…

深度学习在知识图谱问答中的革新与挑战

目录 前言1 背景知识2 基于深度学习改进问句解析模型2.1 谓词匹配2.2 问句解析2.3 逐步生成查询图 3 基于深度学习的端到端模型3.1 端到端框架3.2 简单嵌入技术 4 优势4.1 深入的问题表示4.2 实体关系表示深挖4.3 候选答案排序效果好 5 挑战5.1 依赖大量训练语料5.2 推理类问句…

【原创 附源码】Flutter海外登录--Tiktok登录最详细流程

最近接触了几个海外登录的平台&#xff0c;踩了很多坑&#xff0c;也总结了很多东西&#xff0c;决定记录下来给路过的兄弟坐个参考&#xff0c;也留着以后留着回顾。更新时间为2024年2月7日&#xff0c;后续集成方式可能会有变动&#xff0c;所以目前的集成流程仅供参考&#…

uniapp的配置和使用

①安装环境和编辑器 注册小程序账号 微信开发者工具下载 uniapp 官网 HbuilderX 下载 首先先下载Hbuilder和微信开发者工具 &#xff08;都是傻瓜式安装&#xff09;&#xff0c;然后注册小程序账号&#xff1a; 拿到appid&#xff1a; ②简单通过demo使用微信开发者工具和…

Ribbon全方位解析:构建弹性的Java微服务

第1章 引言 大家好,我是小黑,咱们今天聊聊Ribbon,这货是个客户端负载均衡工具,用在Spring Cloud里面能让咱们的服务调用更加灵活和健壮。负载均衡,听起来挺高大上的,其实就是把外界的请求平摊到多个服务器上,避免某个服务器压力太大,其他的却在那儿闲着。 Ribbon的牛…

npm install express -g报错或一直卡着,亲测可解决

问题描述&#xff1a; 最近学习vue3前端框架&#xff0c;安装Node.js之后&#xff0c;在测试是否可行时&#xff0c;cmd窗口执行了&#xff1a;npm install express -g&#xff0c;发现如下图所示一直卡着不动&#xff0c;最后还报错了&#xff0c;网上找了好久&#xff0c;各…

Springboot根据环境读取application配置文件

目录 1. 首先创建两个不同配置文件 2. pom.xml 配置文件 3. 指定环境 4. 最后启动测试 1. 首先创建两个不同配置文件 分别为开发环境和生产环境 application-dev.properties 和 application-prod.properties application-dev.properties 配置为 1931 端口 application-pro…

12个最常用的matplotlib图例 !!

文章目录 1、折线图 2、散点图 3、直方图 4、柱状图 5、箱线图 6、热力图 7、饼图 8、面积图 9、等高线图 10、3D图 11、时间序列图 12、树状图 总结 1、折线图 折线图&#xff08;Line Plot&#xff09;&#xff1a;用于显示数据随时间或其他连续变量的变化趋势。在实际项目中…

奇异果投屏的进化之路

笔者按&#xff1a;奇异果投屏伴随奇异果TV一路发展至2022年&#xff0c;日活用户已达300多万&#xff0c;用户和我们都对投屏的功能和性能提出了更多的诉求和更高要求&#xff0c;因此2022开始系统地对投屏功能和性能做了扩展和优化。本文立足于TV端&#xff0c;为大家介绍爱奇…

百家cms代审

环境搭建 源码链接如下所示 https://gitee.com/openbaijia/baijiacms 安装至本地后 直接解压到phpstudy的www目录下即可 接下来去创建一个数据库用于存储CMS信息。&#xff08;在Mysql命令行中执行&#xff09; 接下来访问CMS&#xff0c;会默认跳转至安装界面 数据库名称和…
最新文章