[qt] 多线程应用01

news2024/9/20 9:08:44

源码: 点击此处

一 多线程应用

  • 实现一个多线程的网络时间服务器,利用多线程功能的技术,为每个客户端返回当前的时间,并且在返回后自动退出。同时,服务器也会记录当前受到的请求次数。
  • 其实这相当于一个ntp时间服务器

二 服务器实现

2.1 创建服务器UI

  • 首先我们值得注意的是,这些new出来的对象都没有进行释放,是因为对于qt来说他的布局管理器会接管该布局上的控件或布局的所有权,并且我们在vLayout布局上设置了父类指针this,此时当这个类被释放时,vLayout和其上面的控件都会被释放。

#include <QDialog>

class QLabel;
class QPushButton;
class MainWindow : public QDialog
{
    Q_OBJECT

public:
    MainWindow(QDialog *parent = nullptr);
    ~MainWindow();

private:
    QLabel *m_label1;    // 显示监听端口
    QLabel *m_label2;    // 显示请求次数
    QPushButton *m_btn;  // 退出按钮
};


MainWindow::MainWindow(QDialog *parent)
    : QDialog(parent)
{
    setWindowTitle("多线程时间服务器");
    m_label1 = new QLabel(tr("服务器端口"));
    m_label2 = new QLabel;
    m_btn    =  new QPushButton(tr("退出"));
    QHBoxLayout *hLayout = new QHBoxLayout;
    hLayout->addStretch(1);
    hLayout->addWidget(m_btn);
    hLayout->addStretch(1);
    QVBoxLayout *vLayout = new QVBoxLayout(this);
    vLayout->addWidget(m_label1);
    vLayout->addWidget(m_label2);
    vLayout->addLayout(hLayout);
    connect(m_btn,&QPushButton::clicked,this,&MainWindow::close);

    m_count = 0;
    m_server = new CTcperver(this);
    if(!m_server->listen())
    {
        QMessageBox::critical(this,tr("多线程时间服务器"),tr("无法启动服务器: %1").arg(m_server->errorString()));
        close();
        return;
    }
    m_label1->setText(tr("服务器端口: %1").arg(m_server->serverPort()));
}

2.2 创建服务器处理socket

  • 首先我们继承QThread并重写run方法,但是要切记的是,这里的构造函数要传入socket描述符。
  • tcpSocket.setSocketDescriptor(m_sockerIntptr):用socket描述来构造出一个socket连接。
  • 这里使用数据流的方式写入数据,并且设置了数据流版本,这很重要,能够保证写入和读取的版本兼容性,因为当您设置数据流版本时,QDataStream会对数据进行特定版本的序列化处理。这意味着在序列化过程中,数据会被按照特定版本的要求进行格式化。
#include <QThread>
#include <QTcpSocket>

class CTimeThread : public QThread
{
    Q_OBJECT
public:
    explicit CTimeThread(int socketDescriptor,QObject *parent = nullptr);
protected:
    void run() override;

signals:
    void error(QTcpSocket::SocketError errStr);

private:
    int m_sockerIntptr;
};
CTimeThread::CTimeThread(int socketDescriptor,QObject *parent)
    :socketDescriptor(m_sockerIntptr),QObject{parent}
{}

void CTimeThread::run()
{
    QTcpSocket tcpSocket;
    if(!tcpSocket.setSocketDescriptor(m_sockerIntptr))
    {
        emit error(tcpSocket.error());`
            return;
    }
    QByteArray block;
    QDataStream out(&block,QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_12);
    uint time = QDateTime::currentDateTime().toSecsSinceEpoch();
    out<<time;
    tcpSocket.write(block);  // 将获取的当前时间传回客户端
    tcpSocket.disconnectFromHost(); // 断开连接
    tcpSocket.waitForDisconnected(); // 等待返回
}

2.3 服务器类

  1. 创建了一个继承自QTcpServer的类,
  2. 在成员函数中创建了一个之前创建的MainWindow也就是服务器的ui类
  3. 并且在构造函数中直接用传入的parent给他转换,这里首先要理解,对于C++继承来说,必须构造父类的构造函数才能构造成功,而QTcpServer就是构造父类,而(parent)的作用只是传递当前类的父对象,告诉qt的内存管理机制。本类的父对象是哪个。
  4. 然后在incoming里面进行的socket的处理,使用socket描述符创建对应的线程来处理。
  5. 在connect函数中处理了socket的线程的资源释放。
#include <QTcpServer>

class MainWindow;
class CTcperver : public QTcpServer
{
    Q_OBJECT
public:
    explicit CTcperver(QObject *parent = nullptr);
protected:
    void incomingConnection(int sockerDescriptor);
private:
    MainWindow *dlg;
};


CTcperver::CTcperver(QObject *parent)
    : QTcpServer(parent)
{
    dlg = (MainWindow *)parent;
}

void CTcperver::incomingConnection(int sockerDescriptor)
{
    CTimeThread *thread = new CTimeThread(sockerDescriptor,0);
    connect(thread,&CTimeThread::finished,dlg,&MainWindow::slotShow);
    connect(thread,&CTimeThread::finished,thread,&CTimeThread::deleteLater,Qt::DirectConnection);
    thread->start();
}

2.4 调用

    MainWindow w;
    w.show();

三 继承问题

  • 对于C++的子类继承父类必须要构造父类的构造函数
  • 在qt中使用构造函数比如上面的QTcpServer(parent),其实包含两个作用,第一完成基类的构造函数,而将传入的parent给当前类设置了父对象。

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

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

相关文章

C语言 | Leetcode C语言题解之第326题3的幂

题目&#xff1a; 题解&#xff1a; bool isPowerOfThree(int n){int count0;while(n){countn%3;n/3;}return count1?true:false;}

个人对TCP流量控制与拥塞控制的理解

TCP 协议和 UDP 协议 TCP 作为最常用的两大传输层协议之一&#xff0c;无疑是久经生产环境检验的。传输层有两个我们广泛使用的协议&#xff1a;UDP 协议、TCP 协议&#xff0c;我们一般会说前者是面向无连接的&#xff0c;后者是面向连接的。 这里的 “连接” 具体是什么意思…

Prometheus-v2.45.0 + 钉钉告警

目录 1. 创建一个钉钉内部群 2. 添加自定义机器人 3. 配置钉钉发送告警服务 4. 配置alertmanager&#xff0c;接入dingding 5. 配置告警消息发送模板 6. 修改配置规则文件 续接上篇&#xff1a;https://blog.csdn.net/Lzcsfg/article/details/140851688 相关软件包链接…

sqli-labs环境搭建以及部分sql注入

sqli-labs靶场搭建&#xff1a; 安装phpstudy并创建网页 初始化靶场 实现sql注入&#xff1a; less-1&#xff08;根据数据库的命令在超链接后输入?id1&#xff09; less-2&#xff08;如法炮制?id2&#xff09; less-3&#xff08;闭合单引号和括号&#xff09; less-9&am…

新增AI Copilot,DataEase开源数据可视化分析工具v2.9.0发布

2024年8月5日&#xff0c;人人可用的开源数据可视化分析工具DataEase正式发布v2.9.0版本。 这一版本的功能变动包括&#xff1a;导航栏新增Copilot入口&#xff0c;借助AI技术&#xff0c;通过自然语言交互实现即问即答&#xff0c;让数据分析更加直观和便捷&#xff1b;图表方…

vxe-pulldown下拉容器的使用,覆盖样式z-index来解决在Modal中初次显示在Modal的下层的问题。

1、官网的例子&#xff1a; 可以说这个vxe-pulldown用起来还是挺方便的。 2、代码&#xff1a; <template><div><vxe-pulldown ref"pulldownRef" popup-class-name"my-dropdown4" transfer><template #header><div class&quo…

FFMPEG 序列帧图片合成视频

需求&#xff1a; 将多张.png图片合成为视频 注意: 1需要Windows电脑 2将图片重命名 下载EXE 官网 https://ffmpeg.org/download.html#build-windows 解压后长这样 将图片和exe放在同一目录下 文件中找个空白地&#xff0c;Shift右键 进入PowerShell 输入命令: ./ffm…

Chapter 27 封装

欢迎大家订阅【Python从入门到精通】专栏&#xff0c;一起探索Python的无限可能&#xff01; 文章目录 前言一、基本概念二、私有成员 前言 在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;封装是一个重要的概念&#xff0c;旨在保护数据并限制对对象内部状态的直接…

48天笔试训练错题——day41

目录 选择题 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 编程题 1. 五子棋 2. Emacs计算器 选择题 1. 当发生拥塞时&#xff0c;TCP 有个机制&#xff0c;会从慢开始进行发送。 1. 把慢开始的门限值设为当前窗口的一半&#xff0c;即 ssthresh 1/2 * 8 4 KB 2. 把拥塞窗…

【TS】declare 全局声明方式

declare关键字 declare是描述TS文件之外信息的一种机制&#xff0c;它的作用是告诉TS某个类型或变量已经存在&#xff0c;我们可以使用它声明全局变量、函数、类、接口、类型别名、类的属性或方法以及后面会介绍的模块与命名空间。 declare关键字用来告诉编译器&#xff0c;某…

【C语言】关于字符串函数的使用及模拟实现(2)

一、字符串的复制 1.1 库函数strcpy的使用 在函数strcpy中&#xff0c;函数的返回类型为char* &#xff0c;参数部分首先是指向目标地址的指针&#xff0c;其次是指向源地址的指针(由于源地址中内容不受影响&#xff0c;则可以使用const修饰)&#xff0c;函数所需的头文件为st…

51单片机—串口

一、 串口基本认知 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方 式的扩展接口。串行接口&#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简 单&a…

#70结构体案例1(导师,学生,成绩)

效果&#xff1a; 代码&#xff1a; #include <iostream> #include <string> using namespace std;#include "random"int get_random_num(int min,int max) {random_device rd;mt19937 gen(rd());uniform_int_distribution<> dis(min,max);int ra…

C语言实现常见O(N^2)的排序算法

目录 1.排序的概念及常见排序算法 1.1排序的概念 1.2常见的排序算法 2.常见O(N^2)排序算法的实现 2.1插入排序 2.1.1基本思想 2.1.2直接插入排序 2.1.2.1直接插入排序的特性 2.1.2.2直接插入排序算法实现 2.2选择排序 2.2.1基本思想 2.2.2直接选择排…

【电脑基础硬件】磁盘阵列

磁盘阵列 一、磁盘阵列概述作用&#xff1a;RAID级别&#xff1a; 二、Raid0Raid1 一、磁盘阵列概述 磁盘阵列&#xff08;Disk Array&#xff09;是一种将多个独立的磁盘驱动器组合起来形成一个逻辑单元的技术&#xff0c;目的是为了提高存储系统的性能、可靠性和可用性。磁盘…

关于儿童编程语言

青少年通常会通过Scratch或Python开始学习编程。在这两种语言中&#xff0c;代码的编写&#xff08;或者在Scratch中是构建&#xff09;方式类似于英语&#xff0c;这使得初学者更容易学习。Scratch的一个重要卖点是对视觉和运动感知学习者非常友好。这些代码块按颜色编码&…

亚信安全获国家信息安全服务(风险评估和安全工程类)二级资质

近日&#xff0c;亚信安全荣获由中国信息安全测评中心颁发的《国家信息安全测评信息安全服务资质证书—风险评估二级》和《国家信息安全测评信息安全服务资质证书—安全工程类二级》资质。亚信安全凭借综合实力和优秀的技术能力&#xff0c;成为为数不多的获得国家信息安全服务…

PXE无人值守

PXE介绍 预启动执行环境&#xff08;Preboot eXecution Environment&#xff0c;PXE&#xff09;也被称为预执行环境&#xff0c;提供了一种使用网络接口&#xff08;Network Interface&#xff09;启动计算机的机制。这种机制让计算机的启动可以不依赖本地数据存储设备&#…

支持跨设备操作,自带横向霍尔感应滚轮,雷柏MT760系列鼠标上手

日常工作中&#xff0c;确实很需要一只专为商务办公设计的鼠标&#xff0c;这类鼠标通常会有更低调的外观&#xff0c;同时具备静音按键之类的设计&#xff0c;能够为工作带来更多的方便。我最近上手了雷柏MT760和MT760 Mini。这两款鼠标虽然尺寸不同&#xff0c;但共享了相同的…

12.upload-labs靶场通关详解(11~17)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1、Pass11&#xff08;白名单&#xff1a;get00截断&#xff09;2、Pass12&#xff08;白名单&#xff1a;post00截断&#xff09;3、Pass13&#xff08;图片马绕过…