【QT】手把手制作一个网络调试助手(UDP设计)

2023-05-16

TCP和UDP网络通信类的使用

Pornhub

1. 程序框架搭建

接着上一篇文章,这里就开始设计UDP的相关功能函数了,首先将其UDP的相关配置进行隐藏;

1.1 构造函数讲解


MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow)  

其意义是执行父类QWidget的构造函数,创建一个Ui::MainWindow的类对象ui。这个UI就是Widget的private部分定义的指针变量ui。

构造函数里执行了ui->setupUi(this);相当于执行了Ui::Widget类的setupUi()函数,这个函数可以实现窗口的生成与各种属性的设置、信号与槽的关联。

析构函数则是删除new创建的指针ui。 

1.2 屏蔽UDP组件

我们希望在界面初始状态下UDP的组件不被显示出来。

    ui->txtUdpTxIP->hide();
    ui->spbUdpTxPort->hide();
    ui->cbbTxPort->hide();

1.3 声明UDP对象

在头文件中的private中申明一个UDP类的对象;

QUdpSocket *udp;

再在.cpp中进行申明;

udp = new QUdpSocket(this);

2. UI初始化准备工作

2.1 列出支持的网络通信类型

头文件public:初始化:void listNetworkType(QComboBox *cbbNetworkType);

/**
 * @brief MainWindow::listNetworkType 列出支持的网络通信类型
 * @param cbbNetworkType
 */
void MainWindow::listNetworkType(QComboBox *cbbNetworkType)
{
    QMetaEnum mtaEnum = QMetaEnum::fromType<MainWindow::NetworkType>();
    for (int i = 0; i < mtaEnum.keyCount(); i++) {
        cbbNetworkType->addItem(mtaEnum.key(i), mtaEnum.value(i));
    }
    cbbNetworkType->setCurrentText("UDP"); // 设定默认值
}

2.2 获取主机的IPV4

头文件public:初始化:QStringList getHostAddress();

/**
 * @brief MainWindow::getHostAddress 获取主机的 IPv4
 */
QStringList MainWindow::getHostAddress()
{
    QList<QHostAddress> addrList = QNetworkInterface::allAddresses();
    QStringList tmp;
    foreach (QHostAddress hostAddr, addrList){
        if(hostAddr.protocol() == QAbstractSocket::IPv4Protocol){
            if(hostAddr.toString().contains("127.0.")) continue;
            tmp<<hostAddr.toString();
        }
        else if (hostAddr.isNull())  // 主机地址为空
            continue;
    }
    return tmp;
}

2.3 UDP、TCP模式下界面修改

头文件public:初始化:void initComboBoxUDP();

void MainWindow::initComboBoxUDP()
{
    ui->lblIP->setText("本地IP");
    ui->btnLink->setText("连接");
    ui->cbbTxPort->hide();
    ui->txtUdpTxIP->show();
    ui->spbUdpTxPort->show();
}

TCPServer模式下界面修改 

void initComboBoxServer();

void initComboBoxClient();

/**
 * @brief MainWindow::initComboBoxServer 界面修改 服务器
 */
void MainWindow::initComboBoxServer()
{
    ui->lblIP->setText("本地IP");
    ui->btnLink->setText("监听");
    ui->txtUdpTxIP->hide();
    ui->spbUdpTxPort->hide();
    ui->cbbTxPort->show();
}
/**
 * @brief MainWindow::initComboBoxClient 界面修改 客户端
 */
void MainWindow::initComboBoxClient()
{
    ui->lblIP->setText("远程IP");
    ui->btnLink->setText("连接");
    ui->txtUdpTxIP->hide();
    ui->spbUdpTxPort->hide();
    ui->cbbTxPort->show();
}

2.4 UDP初始化下拉列表

头文件public:初始化:void initComboBox_Config();

/**
 * @brief MainWindow::initComboBox_Config 初始化下拉列表
 *
 */
void MainWindow::initComboBox_Config()
{
    this->listNetworkType( ui->cbbNetType );
    QStringList hostAddrList = getHostAddress();
    if( !hostAddrList.isEmpty() )
        ui->txtIP->setText( hostAddrList.at(0) );
    this->initComboBoxUDP();
}

2.5 下拉列表切换三种通信模式

/**
 * @brief MainWindow::on_cbbNetType_currentIndexChanged 切换通信模式
 * @param index
 */
void MainWindow::on_cbbNetType_currentIndexChanged(int index)
{
    switch(index){
    case TCPServer:
        this->initComboBoxServer();
        break;
    case TCPClient:
        this->initComboBoxClient();
        break;
    case UDP:
        this->initComboBoxUDP();
        break;
    }
}

2.6 连接按钮事件

获取下拉列表的值:

    enum NetworkType{
        TCPServer  = 0,
        TCPClient  = 1,
        UDP        = 2,
    };
    Q_ENUM(NetworkType)
    NetworkType networkType = (NetworkType)ui->cbbNetType->currentIndex();

列出枚举的类型,根据下拉列表读取当时的值;

然后进行判断,如果已经点击连接按键;判断下拉列表的值,如果是TCPServer则进行监听,如果是TCPClient则进行连接远端的服务器,如果是UDP则绑定端口号;

如果没有点击连接,则断开上述接口;

在头文件声明指针;

   QTcpServer *server;
    QTcpSocket *client;
    QList<QTcpSocket *>clients;
void MainWindow::on_btnLink_clicked(bool checked)
{
    NetworkType networkType = (NetworkType)ui->cbbNetType->currentIndex();

    bool ok = false;
    if(checked){
        switch(networkType){
        case TCPServer:
      //      ok = this->startListen();
            break;
        case TCPClient:
     //       ok = this->connectRemoteServer();
            break;
        case UDP:
     //       ok = this->bindAddrAndPort();
            break;
        }
        ok? ui->cbbNetType->setEnabled(false): ui->cbbNetType->setEnabled(true);
    }else{
        switch(networkType){
        case TCPServer:
      //      this->stopListen();
            break;
        case TCPClient:
     //       this->disconnectRemoteServer();
            break;
        case UDP:
      //      this->unbindAddrAndPort();
            break;
        default:break;
        }
        ui->cbbNetType->setEnabled(true);
    }
}

现在根据上述流程,将相关函数进行完善;

2.7 UDP通信

UDP每次发送数据报都要指定目标地址端口号;

QUdpSocket *udp;在头文件中声明UDP类用于实现UDP通信;

进行UDP数据接收需要使用

QUdpSocket::bid()函数绑定一个端口;用于接收传入数据报,

udp->bind( *ip, port );

获取客户端IP;获取端口号;

监听函数,返回bool值;

2.7.1 添加状态显示StatusBar

右击,选择添加状态栏;

在提升类的名称中命名为statusBar

ui->statusBar->showMessage("正在监听");

 2.7.2 定义槽函数

public slots:
    void slots_udpRxCallback();

2.7.3 插入时间戳

/**
 * @brief MainWindow::insertTimeStamp 插入时间戳前缀
 * @param tmp
 */
void MainWindow::insertTimeStamp(QString &tmp)
{
    QTime currentTime = QTime::currentTime();
    tmp.prepend( "[" + currentTime.toString("hh:mm:ss:zzz") + "]");
}

2.7.4 数据记录在RxBrowser中

/**
 * @brief MainWindow::logInRxBrowser 数据记录在RxBrowser中
 * @param ipInfo ip,port
 * @param tmp
 */
void MainWindow::logInRxBrowser(QString ipInfo, QByteArray &tmp)
{
    if(ui->ckbTimeStamp->isChecked())
        this->insertTimeStamp(ipInfo);

    QString msg;
    if( ui->ckbHexRx->isChecked() ){
        msg = tmp.toHex(' ').toUpper();
    }else{
        msg = QString::fromLocal8Bit(tmp);
    }
    ui->txtRxBrowser->append( ipInfo + msg );
}

判断;时间戳添加;

判断;转化为十六进制;

txtRxBrowser文本框输出ip信息和数据信息

2.7.5 发出信息插入服务器信息

/**
 * @brief MainWindow::insertServerInfo 插入服务器信息
 * @param tmp
 */
void MainWindow::insertTxInfo(QString &tmp)
{
    QString ip ;
    QString port;
    NetworkType networkType = (NetworkType)ui->cbbNetType->currentIndex();
    switch(networkType){
  case TCPServer :
        ip       = server->serverAddress().toString();
        port     = QString::number( server->serverPort() );
        break;
    case TCPClient:
        ip       = client->localAddress().toString();
        port     = QString::number( client->localPort() );
        break;
    case UDP:
        ip       = ui->txtIP->text();
        port     = ui->txtPort->text();
        break;
    }
    tmp.prepend( "[" + QString("Tx from %1:%2").arg(ip, port) +"]\n" );
}

2.7.6 接收插入发送端IP和端口号

/**
 * @brief MainWindow::insertRxInfo 插入发送端的IP和端口号
 * @param client
 * @param tmp
 */
void MainWindow::insertRxInfo(QNetworkDatagram *datagram, QString &tmp)
{
    QString ip = datagram->senderAddress().toString();
    QString port = QString::number( datagram->senderPort() );
    tmp.prepend( "[" + QString("Rx from %1:%2").arg(ip, port) +"]\n" );
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【QT】手把手制作一个网络调试助手(UDP设计) 的相关文章

  • UDP 服务器套接字缓冲区溢出

    我正在 Linux 上编写 C 应用程序 我的应用程序有一个 UDP 服务器 它在某些事件上向客户端发送数据 UDP 服务器还接收来自客户端的一些反馈 确认 为了实现这个应用程序 我使用了一个 UDP 套接字 例如int fdSocket
  • Spark Scala UDP 在侦听端口上接收

    中提到的例子http spark apache org docs latest streaming programming guide html http spark apache org docs latest streaming pro
  • UdpClient 在广播地址上接收

    在 c 中 我使用 UdpClient Receive 函数 public void StartUdpListener Object state try udpServer new UdpClient new IPEndPoint IPAd
  • NTP请求包

    我试图弄清楚我需要在 NTP 请求包中发送 客户端 什么才能从服务器检索 NTP 包 我正在 Cortex M3 Stellaris LM3S6965 上使用 LWIP 据我了解 我将收到 UDP 标头 然后收到具有不同时间戳的 NTP 协
  • 为什么我的 UDP 广播失败?

    我正在尝试发送 UDP 广播 但wireshark 没有报告任何流量 这是执行发送的代码片段 void SendBroadcast String ip 255 255 255 255 int port 30718 String messag
  • C++ 反序列化通过 UDP 从 C# 应用程序发送的对象

    我有一个申请c 它连接到另一个应用程序 编写为c 通过UDP 我更喜欢高性能的解决方案 因为我希望测量事件客户端 某些处理服务器端和客户端处理完成的响应之间的时间 本质上是 往返延迟 我有一个 C 对象 例如 public class Pa
  • 通过 Internet 发送 UDP 数据包

    我正在尝试了解 P2P 去中心化网络的一些细节 我的问题如下 假设我有两台名为 comp1 和 comp2 的机器 现在 comp1 设置在我的家庭网络中的路由器后面 comp2 位于我的办公室中 也位于路由器后面 我是否可以像这样在 In
  • DatagramChannel.close() 在 Windows 上保持端口打开

    我正在实施一个发现流程 打开 UDP 套接字以侦听给定端口上的广播响应 发送一些请求 并期待稍后的响应 在给定时间段后关闭 UDP 套接字 第一次通话有效 但其他调用会出现绑定错误 地址已被使用 绑定 我运行的是Windows 7 我做了一
  • 将 Docker 容器连接到网络接口/设备而不是 IP 地址

    经过仔细的研究 测试和摆弄 我只能找到通过从 IP 端口转发来将 Docker 容器连接到给定接口的方法 这可以通过添加来完成 p Host IP Host Port Container Port to a docker run命令 我有一
  • 当网络上的所有计算机都具有相同的公共IP地址时,如何向特定计算机发送UDP数据包? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 这就是问题 它非常简单 理解 我家里有 2 台电脑 它们都有相同的公共 IP 地址 例如 1 2 3 4 我在咖啡馆有一台计算机 不同的网络 因此它具
  • VS2015:应用程序无法正确启动(0xc000007b)

    我在 Visual Studio 2015 上为 Windows 10 PC 编写了代码 该应用程序主要关注 UDP 通信 我使用 boost 库 它工作正常 但当我将代码文件夹移至 Windows 7 时 我收到错误 应用程序无法正确启动
  • 什么是消息边界?

    什么是 消息边界 在以下情况下 TCP 和 UDP 之间的区别之一是 UDP 保留消息 边界 我理解之间的区别TCP and UDP 但我不确定的定义 消息边界 由于 UDP 在每个单独的数据包中包含目的地和端口信息 因此是否可以为消息提供
  • 互联网上的 UDP 多播?

    我不确定如何最好地解决我的问题 我有一个在远程计算机上运行的服务 用于接收和处理 UDP 数据包 我希望该服务能够将这些数据包重新发送给任何需要它们的人 可能是任何人 通常是一台机器 但也可能更多 我认为 UDP 多播将是理想的 该服务可以
  • 为什么我们可以将 sockaddr 转换为 sockaddr_in

    我明白为什么强制转换很有用sockaddr to sockaddr in 但我不明白这怎么可能 据我所知 它们的大小相同sockaddr in添加了sin zero使其大小相同 我想知道编译器如何知道从哪里获取信息sockaddr in如果
  • 使用 STUN 打孔

    我目前正在尝试通过 Internet 发送 UDP 消息 并且必须为端点 A 和 B 都位于 NAT 后面 设置防火墙 为此 我想使用 STUN 服务器进行打孔 当 A 创建对 STUN 服务器的请求 例如 私有 85 1 1 12 600
  • 您可以bind()和connect() UDP连接的两端吗

    我正在编写一个点对点消息队列系统 它必须能够通过 UDP 运行 我可以任意选择一侧或另一侧作为 服务器 但这似乎不太正确 因为两端都从另一端发送和接收相同类型的数据 是否可以绑定 和连接 两端 以便它们只能彼此发送 接收 这似乎是一种非常对
  • 为多线程 UDP 客户端执行“close ()”时套接字描述符未释放

    我在下面编写了 UDP 客户端 它基本上生成一个单独的线程来接收数据报 但是数据报仅在主线程中发送 现在 在 Linux 发行版上实例化 udpClient 1 UDP 客户端后按 ctrl D 实现退出循环 围绕 getline 调用 并
  • 为什么 UDP 服务器中只有一个套接字?

    我正在准备考试 发现了这个问题 典型的 UDP 服务器可以使用单个套接字来实现 解释一下为什么 对于 TCP 驱动的服务器 我发现创建了两个套接字 一个用于所有客户端访问服务器 另一个用于每个客户端的特定 套接字 用于服务器和客户端之间的进
  • 为什么 Kademlia 使用 UDP?

    为什么Kademlia 分布式哈希表 http en wikipedia org wiki Kademlia使用 UDP 作为其网络传输协议 即使它不可靠 主要原因是您快速查询了许多以前从未建立过联系并且可能在查找过程中永远不会再看到的节点
  • 如何读取 UDP 连接直至超时?

    我需要读取 UDP 流量 直到超时 我可以通过在 UDPConn 上调用 SetDeadline 并循环直到出现 I O 超时错误来做到这一点 但这看起来很黑客 基于错误条件的流量控制 下面的代码片段看起来更正确 但并没有终止 在生产中 这

随机推荐

  • GPU渲染管线之旅|08 Pixel Shader

    在这一部分中 xff0c 我们来谈谈像素处理的前半部分 dispatch和实际的像素着色 事实上 xff0c 这部分是大多数图形开发者在谈到PS stage时所关心的内容 有关alpha blend和Late Z的内容则会下一篇文章中去探讨
  • MFC基于CSplitterWnd类的多窗口分割

    使用平台 xff1a win7 64bit 使用环境 xff1a VS2012 1 CSplitterWnd介绍 上图是从MSDN中截取的类的继承图表 xff0c CSplitterWnd类继承自CWnd类 这个类主要就是提供窗口分割的功能
  • OpenCV - 区域生长算法

    1 理论基础 区域生长算法的基本思想是将有相似性质的像素点合并到一起 对每一个区域要先指定一个种子点作为生长的起点 xff0c 然后将种子点周围领域的像素点和种子点进行对比 xff0c 将具有相似性质的点合并起来继续向外生长 xff0c 直
  • 不规则Contours内部像素的操作

    在findContours函数使用了之后 xff0c 有时候就会面临对Contours内部区域的访问 由于contours不一定是凸图形 xff0c 所以使用循环操作的时候总感觉不那么方便 比如在下图中 xff0c 已经使用findCont
  • ros代码中添加使用opencv库,cv::Mat和ros image之间的相互转换

    https blog csdn net sunyoop article details 78630024 ros中很多时候要用到图形处理 xff0c 这时就需要使用opencv库 xff0c 本篇主要将怎么在ros现成node上使用open
  • Ubuntu 16.04 使用

    这篇博客用来专门记录尝试搬迁工作环境到Linux下的使用笔记 xff0c 主要包含有常用软件的安装 xff0c 配置 1 安装输入法 ubuntu 16 04中支持ibus输入系统 1 系统 gt 首选项 gt IBus设置 在弹出的IBu
  • 牛顿迭代法求解方程

    说明 xff1a 该篇博客源于博主的早些时候的一个csdn博客中的一篇 xff0c 由于近期使用到了 xff0c 所以再次作一总结 原文地址 概述 牛顿迭代法 xff08 Newton s method xff09 又称为牛顿 拉夫逊 xf
  • OpenCV - 均值迭代分割

    题外话 之前在博客中写过一篇 区域生长 的博客 xff0c 区域生长在平时经常用到 xff0c 也比较容易理解和代码实现 xff0c 所以在很多情况下大家会选择这种方法 但是区域生长有一个最致命的点就是需要选取一个生长的种子点 为了交流学习
  • IMU原理及姿态融合算法详解

    IMU原理及姿态融合算法详解 一 组成 IMU全称是惯性导航系统 xff0c 主要元件有陀螺仪 加速度计和磁力计 其中陀螺仪可以得到各个轴的加速度 xff0c 而加速度计能得到x xff0c y xff0c z方向的加速度 xff0c 而磁
  • FrankMocap win10安装指导

    本文是相当于将github上frankmocap的安装指导进行了翻译 xff0c 增加了一下windows下安装遇到的坑以及注意事项 如果是linux系统应该安装官方的安装指导安装就可以 xff0c 可以直接参考官方安装指导 安装所有模块
  • ADRC学习(1)系统在调节过程中安排过渡过程的作用

    1 二阶系统的调节过程 考虑对于如下所示的二阶系统 x
  • 笔记本更换SSD后卡顿、假死、失去响应问题探究

    某些笔记本电脑将HDD更换为SSD后 xff0c 系统运行过程中会随机产生半分钟到一分钟的卡顿 xff08 假死 xff09 期间鼠标指针可以运动 xff0c 但所有程序均失去响应 xff0c 也无法打开新的程序 HDD硬盘指示灯常亮 xf
  • 机器人 齐次变换矩阵 位姿变换矩阵(RT矩阵) Matlab参数公式计算

    对于齐次位姿变换 xff08 RT矩阵 xff09 xff0c 有的时候手动计算公式参数太多比较麻烦 xff0c 因此利用matlab参量syms xff0c 可以方便一些 xff0c 可以用于计算机器人正运动学位姿矩阵的参数表示 xff0
  • UART串口校验方式(无校验、奇偶校验、固定校验)

    UART串口校验方式 xff08 奇偶校验 固定校验 无校验 xff09 串口通信校验方式奇偶校验位固定校验位 Stick 无校验位 校验位 xff1a 串口通信中的检错方式 串口在接收数据时 xff0c 如果无检验位 xff0c 则只要检
  • 更改LXDE的语言为中文

    之前给旧笔记本安装了Debian8 43 LXDE嘛 xff0c 运行比较流畅 安装过程中本想选择中文的 xff0c 但是安装界面中旧有中文乱码 xff0c 所以还是选了英语 等装好了系统 xff0c 把apt update 43 upgr
  • 干掉Nouveau安装Linux Nvidia显卡驱动

    https blog csdn net misiter article details 7652731 干掉Nouveau安装Linux Nvidia显卡驱动 首先说明下什么是Nouveau xff0c 为什么有些系统安装N卡驱动的时候会提
  • 【C应用】红外遥控小车程序分析(上)——四轮马达方向控制程序分析

    目录 驱动原理分析 L293D功能分析 代码分析 驱动原理分析 小车采用两片L293D芯片控制四个车轮 xff0c 原理图如下 xff1a 因为L293D可分别控制两路电机 xff0c 为了方便理解L293D芯片的工作原理 xff0c 拿L
  • 【RTOS】RTOS实时操作系统随笔(结合UCOSII相关移植)

    目录 无操作系统下的程序结构及缺陷 有操作系统下的解决方案及CPU工作原理 操作系统调度策略及时间片轮转策略 操作系统TICK及进程切换 UCOSII介绍 UCOSII进程任务切换原理 xff1a UCOS进程的堆栈 xff1a 时钟TIC
  • 【STM32CobeMX】CubeMX建立基于STM32F1VBT6的FreeRTOS

    STM32F103VBT6 内部时钟源RCC 如果使用RTOS 使用了RTOS xff0c 默认使用SysTick xff1b 所以HAL库的时基就要用其他的定时器 当用了RTOS xff0c 就要设置HAL的timebase为其他Time
  • 【QT】手把手制作一个网络调试助手(UDP设计)

    TCP和UDP网络通信类的使用 Porn hub 1 程序框架搭建 接着上一篇文章 xff0c 这里就开始设计UDP的相关功能函数了 xff0c 首先将其UDP的相关配置进行隐藏 xff1b 1 1 构造函数讲解 MainWindow Ma