当前位置: 首页 > news >正文

《操作系统实践-基于Linux应用与内核编程》第10章--实验 Qt聊天程序

 前言:

内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容,所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。

引用:

《操作系统实践-基于Linux应用与内核编程》

作者:房胜、李旭健、黄玲、李哲

出版社:清华大学出版社

资源:

 教材资源

链接: https://caiyun.139.com/m/i?1A5Ch36dl1whD  提取码:jdQe

课件和电子资料源码

链接: https://caiyun.139.com/m/i?1A5CvEKY07Uzs  提取码:xyv0

参考链接:

Qt 之网络编程_qt网络编程-CSDN博客

[QT_047]Qt学习之表单布局器(QFormLayout)-CSDN博客

Qt中采用多线程实现Socket编程_parent is qnativesocketenhine parrnt's thread is t-CSDN博客

正文

1. 登录窗口源码

参考电子资源中的源码 '' ch10/QChat/qdlglog.in.cpp",完善Qt聊天程序登录页面的源码。

在Qt Creator 点击 qdlglogin.cpp ,进入编辑页面,参考源码示例增加需要引入的头文件

#include "qdlglogin.h"
#include "ui_qdlglogin.h"//Add by dimon 2024/-0316 14:32, Copy the source code
#include "qdlggchat.h"
#include "common.h"
#include <QMessageBox> //弹出对话框
#include <QHostAddress>

此时发现 Qt Creator 提示错误,说找不到 'QHostAddress'头文件。原因是我们的Qt 项目需要用到 Qt 网络模块,而当前我们还没有引入 Qt 网络模块。

解决方案,参考链接博文,在项目 ".pro"文件中加入一行,在Qt项目中引起 Qt Network 模块,这样Qt Creator 就能找到 "QHostAddress"头文件了。

QT += network

Qt 之网络编程_qt网络编程-CSDN博客文章浏览阅读2.7w次,点赞21次,收藏38次。Qt Network模块提供的类允许编写 TCP/IP clients 和 servers。_qt网络编程https://blog.csdn.net/liang19890820/article/details/52249509

修改 qdlglogin.h 头文件,需要用到 Qt "QTcpSocket" 类,在qdlglogin.h文件头加上对 QtcpSocket的包含。Qt Creator只有在包含对应的头文件后,在Qt Crateor编辑器里才能智能提示补全头文件里的函数,类。

#ifndef QDLGLOGIN_H
#define QDLGLOGIN_H#include <QDialog>
#include <QTcpSocket> //QTcpSocket头文件

在 qdlglogin.h 中类 class qdlglogin 中加上 private 私有成员,登录页面中需要记录的用户ID,密码,服务器IP,服务器端口号,以及 *tcpSocket指针。

修改 qdlglogin.cpp的类构造函数,在构造qdlglogin登录对话框时,设置‘用户名’和‘密码’文本输入框的'LineEdit'的提示符,和密码输入文本对话框'LineEdit’的回显模式为 'LineEdit::Password'对密码做特殊回显。设置登录对话框的“登录”和“注册”按钮"QPushButton'初始化为非Enable模式,灰化不可以点击。

效果如下图

2. Qt布局器的使用

在设置qdlgchar.ui窗体的布局是,使用到了Qt Creator设计师界面的 Qt 布局器,Qt布局器可以使用的有水平布局,和垂直布局。

[QT_047]Qt学习之表单布局器(QFormLayout)-CSDN博客文章浏览阅读3.8k次,点赞2次,收藏17次。Qt学习之表单布局器(QFormLayout)_qformlayouthttps://blog.csdn.net/kongcheng253/article/details/128781000

Qt 布局器的使用技巧是:

1. 第一种方法,直接拖动Qt设计师界面到布局器到ui设计界面,然后拖动需要的widget组件到布局器。实际操作拖动之后,就会发现使用鼠标拖动窗体小组件widget到布局器的方式分非常容易误操作,总是不能选择到想要的小组件,或者小组件在布局器里自动排序出错等。

2. 第二种方法,是参考如上链接中的方法,先一次选中多个需要布局的窗体小组件,点击Qt ui设计菜单上的“打破布局”,破坏原有的布局;然后点击窗体菜单“水平布局”或者“垂直布局”,所选中的多个小组件就会自动加入到Qt布局器中。

注意:小组件被加入到布局器中之后,小组件的大小就不能调整了。如果想要再次调整小组件的大小,可以先选择小组件所在的父布局器 点击“破坏布局”,去掉布局之后就可以单独调整小组件的大小。调整小组件大小到之后,再把组件加入到Qt布局器。

点击右键“选择全部”会选择全部的窗体小组件, 然后点击“水平布局”,选择到的组件就都被加入到“水平布局器”中。

技巧1: 单击小组件的时候,总是会选择到Qt布局器里的一个小组件,有时间我们是想去选中整个Qt布局器。此时可以在ui设计界面右侧的窗体里用鼠标选择它的上一级布局器,就可以很容易的选择到父布局器。

技巧2:按下Ctrl键,鼠标单击右侧窗口中的布局器1,再单击布局器2,就会一次同时选择多个布局器。

3. 聊天窗口源码

参考源码实现 qdlggchar.cpp 的源码。需要设置的 comboBox , toolButton 等设置发送 txtEdit 组件中的字体的“字体”,“加粗”,“倾斜”,“颜色” 等 button关联的槽函数时,进入Ui设计界面,鼠标右键“转到槽”,实现槽函数(从示例代码中抄过来)。通过抄写示例代码的过程,实现了 qdlggchat.cpp 窗体的中按钮逻辑,也进一步接触和实践使用Qt来编程实现需要的功能。

4. 添加聊天服务器项目

新建项目,“QWidgetApplcation”,选择基类QDiaglog

使用Qt布局器,设计Qt聊天服务器的窗体布局。

参考电子资源中的示例源码,添加文件(类)qmydb.cpp(.h), qserver.cpp(.h), qthread.cpp(.h), quser.cpp(.h) 

右键单击"QChatServer"项目,"Add New",“Add C++ Class”,类命名为"qmydb",基类选贼为"QObject",确定,自动生成 qmydb.cpp 源文件和 qmydb.h头文件。

相同的操作,添加"qserver,quser, qthread, qserver” C++ 类的源文件和头文件。

注意: 如果Qt Creator 有多个项目打开,选择“添加到项目”是需要下拉框选择添加到指定的目标Qt项目。如果保持默认可能把文件会添加到不是自己想要的项目中。

4.1 服务器qmydb 数据库连接类

参考电子资源QChatServer源码中 qmydb 类,抄写源码到我们的Qt聊天服务器项目中。

添加头文件时,Qt Creator编辑器提示找不到"QSqlDatabase"头文件,原因项目用到了Qt数据库模块,但还没有把Qt数据库模块引入到我们QChatServer项目中。

如何查看,我们需要引入哪个Qt 数据库模块?

方式是查看Qt提供的帮助手册,在Qt帮助手册中会说明如果我们需要使用某个Qt模块,需要在项目中如何引入该模块。一般是在项目的 “.pro”文件中加上

Qt += xxx(模块名)

点击Qt Creator编辑器左侧菜单栏“帮助”,进入Qt 帮助文档,点击左下的过滤选择下拉框,下拉框里提供了“索引,查抄,书签,打开页面” 这4个选项。如果需要根据关键字搜索Qt 帮助文档,可以下拉框选择“查找”,输入关键字(例如 qsql),就会出现搜索结果,在搜索结果的帮助文档的起始部分,很明确的告诉我们如果书需要使用 Qt Sql模块需要包含头文件"QSqlDatabase",并且工程中需要在QMake中"QT += sql"引入sql模块(修改项目的 .pro文件,在文件结尾加上 QT += xxx)。


Header:
#include <QSqlDatabase> qmake:
QT += sql

我们QChatServer聊天服务器需要用到Qt Sql模块和Qt Network模块,所以在 QChatServer.pro 文件尾部加上如下的两行,就在我们的聊天服务器项目中引入了Qt sql和network项目。

4.2 服务器qtcpthread 处理tcp连接线程
4.3 服务器qserver类

对照着电子资源中的'c10/QChatServer'把源码,手动的敲到Virtualbox Ubuntu18.04 Qt5.14.2 编辑器之后,编译执行,进行联调 QChat 聊天程序。

在 QChatServer 聊天服务器假面,点击“启动服务” 按钮,聊天服务器开始监听来自聊天客户端的TCP连接,当收到聊天客户端的注册请求时, QChatServer 服务器端查询MySQL数据库,看用户是否已经注册,如果没有注册,就把用户插入到MySQL数据库并返回用户登录成功。

QChatServer 收到 QTcpSocket 连接请求时,新创建一个线程。并在线程里通过监听 socket 的 ' SIGNAL(readyRead()' 信号,并把槽函数‘SLOT(onReadyRead())’ 和这个信号函数'readyRead()'关联起来。当 QTcpSocket 有数据可以读取时,信号函数'readyRead()'被触发,发出信号,槽函数‘onReadyRead()’被执行。

槽函数'onReadyRead()'中连接数据库MySQL成功,并把用户注册名加入到 MySQL db_chat 数据库表 tb_chat 中。

QChatServer执行时,在窗口里打印出错误提示信息。

Current thread is:  QThread(0x56053b2b53f0)
tcpSocket wirte QByteArray to socket
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x7fb3b8001b90), parent's thread is QTcpThread(0x56053b6114a0), current thread is QThread(0x56053b2b53f0)
 

百度搜索这个错误信息 ‘ Parent is QNativeSocketEngine(0x7fb3b8001b90), parent's thread is QTcpThread(0x56053b6114a0) ’,从如下链接的博文里解释了Qt 多线程编程里程序执行打印出该提示信息的原因。

Qt中采用多线程实现Socket编程_parent is qnativesocketenhine parrnt's thread is t-CSDN博客文章浏览阅读9.9k次,点赞5次,收藏14次。本文介绍的是Qt中采用多线程Socket编程,由于工作项目的需要,使用Qt的socket编程。Qt里的example是个不错的教程,但是当我把代码移植到多线程的环境时就出问题了:QObject: Cannot create children for a parent that is in a different thread.由于想要在线程中保留一个socket,以便维持双边通信,因此_parent is qnativesocketenhine parrnt's thread is tcprecv currenthttps://blog.csdn.net/ggggyj/article/details/51132225根据如下链接博客里的提示,我们修改QChatServer/qtcpthread.cpp 的程序源码中的信号-槽关联函数connect(),加上' Qt::DirectConnection '。QChatServer服务器再执行时,在新线程里就不会打印之前的错误提示 信息了。

    //connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()), Qt::DirectConnection);

4.4 服务器quser类

相关文章:

《操作系统实践-基于Linux应用与内核编程》第10章--实验 Qt聊天程序

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容&#xff0c;所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者&#xff1a;房胜、李旭健、黄…...

探究Kafka主题删除失败的根本原因

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 探究Kafka主题删除失败的根本原因 前言主题删除的基础主题删除的定义和作用&#xff1a;删除操作的基本流程&#xff1a; 可能存在删除异常的因素数据积压的处理方法Broker状态异常处理方法通用方法 前…...

JavaSE(上)-Day7

JavaSE&#xff08;上&#xff09;-Day7 类和对象封装privatethis构造方法标准JavaBean对象的内存图执行Test类main方法生成一个User对象的内存过程 基本数据类型和引用数据类型的区别this的内存原理成员变量和局部变量区别 类和对象 类是设计图纸&#xff0c;对象是真正的实例…...

记录一下在Pycharm中虚拟环境的创建

如果在Pycharm中要新建一个虚拟环境&#xff0c;那你可以在Terminal中选择Command Prompt&#xff0c;在这里面执行相关命令 一、安装了Anaconda&#xff0c;创建虚拟环境 当你使用解释器是Anaconda提供的时&#xff0c;你可以使用conda命令执行&#xff0c;见以下操作&#x…...

Python从入门到精通秘籍九

一、Python中文件编码概念 在Python中&#xff0c;文件编码指的是将文本内容转换为字节序列的过程。不同的编码方式使用不同的字符集和字节表示形式。下面是一个示例代码&#xff1a; # 写入文本到文件 text "你好&#xff0c;世界&#xff01;" with open("…...

善于利用window挂在全局变量

开发过程成中遇到一个奇怪的问题&#xff0c;打开一个echats图表之后&#xff0c;关闭echarts图再进入其他页面页面会报错提示 $&#xff08;...&#xff09;.draggble not a function经过一步步定位&#xff0c;发现echats图是通过后端获取js、css文件然后在本地绘制而成。而获…...

《C缺陷和陷阱》-笔记(5)

目录 一、整数溢出 溢出 如何防止溢出 二、为函数main提供返回值 连接 一、什么是连接器 连接器工作原理 三、声明与定义 四、命名冲突与static 修饰符 statia 一、整数溢出 溢出 C语言中存在两类整数算术运算&#xff0c;有符号运算与无符号运算。 在无…...

【数字图像处理matlab系列】保存图像

【数字图像处理系列】保存图像imwrite函数 使用函数imwrite可以将图像保存到本地上,该函数的语法为 imwrite(image_data, filename)其中,image_data是要写入的图像数据,可以是一个矩阵或一个三维数组(对于彩色图像),filename是要写入的文件名,可以包含路径信息。例如,…...

八股文三(Spring、Spring Cloud Alibaba)

Spring篇 什么是Spring Spring是个轻量级的框架&#xff0c;他有两大内核分别是IOC、AOPIOC是什么 * 依赖注入和控制反转&#xff0c;它是一种思想&#xff0c;创建对象不是直接new出来&#xff0c;而是交给IOC容器&#xff0c;由容器去创建进行管理&#xff0c;这就是控制反…...

一文带你详解天池工业数据集

人工智能是国家战略性新兴产业&#xff0c;制造业是国民经济的主体&#xff0c;随着人口红利的消失&#xff0c;加强设备自动化改造&#xff0c;提高生产自动化程度&#xff0c;减小劳动强度&#xff0c;改善作业环境&#xff0c;已经成为制造业的普遍共识。天池大赛开放出一批…...

08 龙芯平台openstack部署搭建-neutron-controller部署

一、创建neutron相关数据库、服务凭证和API端点 1.创建neutron数据库&#xff0c;授予合适的访问权限 mysql -uroot -ploongson -e “CREATE DATABASE neutron;” mysql -uroot -ploongson -e “GRANT ALL PRIVILEGES ON neutron.* TO ‘neutron’‘localhost’ IDENTIFIED B…...

JAVA 100道题(6)

6.创建一个表示矩形的类&#xff0c;包括宽度和高度属性&#xff0c;以及计算面积和周长的方法。 下面是一个简单的Python类&#xff0c;表示矩形&#xff0c;包含宽度和高度属性&#xff0c;以及计算面积和周长的方法&#xff1a; python复制代码 class Rectangle: def __ini…...

Leetcode面试经典150题

数组字符串 合并两个有序数组 思路 类似于归并排序&#xff0c;对两个有序数组进行合并即可&#xff0c;但是空间复杂度是O(nm); 代码 class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int[] ans new int[n m];int i 0, j 0;int cnt 0;…...

王者荣耀使用的UDP通信,十几年编程没用过的协议

缘起 最近在查阅moba相关的资料时&#xff0c;看到了一篇王者荣耀的研发同学的技术分享&#xff0c;从文章中了解到王者荣耀的通信方式是UDP通信&#xff0c;回想到整个职业生涯&#xff0c;貌似并没有用过&#xff0c;今天特地整理下。 udp技术细节 udp协议 UDP协议叫做用…...

HiveQL详解

文章目录 前言一、数据定义语言&#xff08;DDL&#xff09;1. 数据库操作1.1 创建数据库1.2 删除数据库1.3 更改数据库1.4 使用数据库 2. 连接器操作2.1 创建连接器2.2 删除连接器2.3 修改连接器 3. 表操作3.1 创建表3.1.1 内部表与外部表3.1.1.1 内部表3.1.1.2 外部表3.1.1.3…...

Linux/Bizness

Enumeration nmap 用 nmap 扫描了常见的端口&#xff0c;发现对外开放了22,80,443 ┌──(kali㉿kali)-[~] └─$ nmap 10.10.11.252 Starting Nmap 7.93 ( https://nmap.org ) at 2024-03-08 01:21 EST Nmap scan report for 10.10.11.252 Host is up (0.36s latency). Not…...

mysql 数据库 增删改查 基本操作

目录 一 SQL 详细介绍 &#xff08;一&#xff09;SQL 分类 &#xff08;二&#xff09; SQL 语言规范 &#xff08;三&#xff09;数据库对象和命名 1&#xff0c;数据库的组件(对象)&#xff1a; 2&#xff0c;命名规则&#xff1a; &#xff08;四&#xff09; SQL…...

计算机网络——物理层(编码与调制)

计算机网络——编码与调制 基带信号和宽带信号编码与调制数字数据编码为数字信号非归零编码归零编码反向不归零编码曼彻斯特编码差分曼彻斯特编码4B/5B编码 数字数据调制为模拟信号模拟数据编码为数字信号模拟数据调制为模拟信号 我们之前讲了物理层的一些基础知识和两个准则&a…...

PHP魔术方法详解

__construct() 构造函数用于初始化新创建的对象。PHP 5 之后不推荐使用类名作为构造函数。 class Person {public $name;public $age;public function __construct($name, $age) {$this->name $name;$this->age $age;} }$person new Person("Alice", 30);…...

游戏 AI 反作弊|内附解决方案详情!

我们提出使用在游戏中广泛存在的回放日志数据&#xff0c;重构出玩家当局的表现。在回放 日志数据中&#xff0c;我们构建了玩家的时序行为数据&#xff0c;并基于该时序行为数据&#xff0c;分别搭建 了透视和自瞄外挂检测系统&#xff0c;该方法和系统可广泛应用于各种在线…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...