QT聊天室阶段性记录(完善中:注册功能,数据库存储)

server.h

#ifndef SERVERDEMO_H
#define SERVERDEMO_H#include <QObject>
#include <QTcpServer>
#include <QMap>
#include <QSqlDatabase> //数据库管理类
#include <QSqlQuery>    //执行sql语句的类
#include <QSqlRecord>   //数据库记录类#include "TextMessage.h"
#include "txtmsgassembler.h"
#include "TxtMsgHandler.h"class ServerDemo : public QObject
{Q_OBJECTQTcpServer m_server;   //服务端类对象QMap<QTcpSocket*, TxtMsgAssembler*> m_map;TxtMsgHandler* m_handler;QSqlDatabase db;
public:ServerDemo(QObject* parent = NULL);bool start(int port);   //启动服务端void stop();            //停止服务端void setHandler(TxtMsgHandler* handler);//设置接口~ServerDemo();protected slots:void onNewConnection(); //新客户端连接槽函数void onConnected();     //连接槽函数void onDisconnected();  //断连槽函数void onDataReady();     //数据接收槽函数void onBytesWritten(qint64 bytes);
};#endif // SERVERDEMO_H

server.cpp

#include "ServerDemo.h"
#include <QHostAddress>
#include <QTcpSocket>
#include <QObjectList>
#include <QDebug>ServerDemo::ServerDemo(QObject* parent) : QObject(parent), m_handler(nullptr)
{//判断字节的数据库对象中是否包含了要处理的数据库,如果没有包含则添加一个数据库,否则直接打开if( !db.contains("user.db") ){//添加一个数据库,调用该类中的静态成员函数db = QSqlDatabase::addDatabase("QSQLITE");//sqlite3//设置数据库名字db.setDatabaseName("user.db");}//打开数据库if( !db.open() ){qDebug() << "数据库打开失败" << endl;return;}//使用sql语句进行表的创建QString sql = "create table if not exists user_info(""username varchar(16) primary key,""password varchar(16),""status varchar(10),""level varchar(10))";//执行语句QSqlQuery querry;if( !querry.exec(sql) ){qDebug() << "表创建失败失败" << endl;return;}connect(&m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
}void ServerDemo::onNewConnection()
{QTcpSocket* tcp = m_server.nextPendingConnection();TxtMsgAssembler* assembler = new TxtMsgAssembler();m_map.insert(tcp, assembler);//用字典容器,为每一个客户端分配一个装配器类对象connect(tcp, SIGNAL(connected()), this, SLOT(onConnected()));connect(tcp, SIGNAL(disconnected()), this, SLOT(onDisconnected()));connect(tcp, SIGNAL(readyRead()), this, SLOT(onDataReady()));connect(tcp, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));if( m_handler != nullptr ){TextMessage msg("CONN", tcp->peerAddress().toString() + ":" + QString::number(tcp->peerPort()));m_handler->handle(*tcp, msg);}
}void ServerDemo::onConnected()
{}void ServerDemo::onDisconnected()
{QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(sender());if( tcp != nullptr ){delete m_map.take(tcp);if( m_handler != nullptr ){TextMessage msg("DSCN", "");m_handler->handle(*tcp, msg);}}
}//循环从缓存区读取数据
void ServerDemo::onDataReady()
{QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(sender());char buf[256] =  {0};int len = 0;if( tcp != NULL ){//通过字典容器找到发送信息的客户端,TxtMsgAssembler* assembler = m_map.value(tcp);while( (len = tcp->read(buf, sizeof(buf))) > 0 ){if( assembler != nullptr ){QSharedPointer<TextMessage> ptm = nullptr;assembler->prepare(buf, len);while( (ptm = assembler->assemble()) != nullptr ){if( m_handler != nullptr ){m_handler->handle(*tcp, *ptm);}}}}}
}void ServerDemo::onBytesWritten(qint64 bytes)
{(void)bytes;
}//开启服务端
bool ServerDemo::start(int port)
{bool ret = true;if( !m_server.isListening() ){ret = m_server.listen(QHostAddress("127.0.0.1"), port);}return ret;
}//停止服务端
void ServerDemo::stop()
{if( m_server.isListening() ){m_server.close();}
}//设置接口
void ServerDemo::setHandler(TxtMsgHandler *handler)
{m_handler = handler;
}//服务端析构
ServerDemo::~ServerDemo()
{const QObjectList& list = m_server.children();for(int i=0; i<list.length(); i++){QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(list[i]);if( tcp != NULL ){tcp->close();}}const QList<TxtMsgAssembler*>& al = m_map.values();for(int i = 0; i < al.length(); i++){delete al.at(i);}
}

server_main.cpp

#include <QCoreApplication>
#include "serverhandler.h"
#include "ServerDemo.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);ServerHandler handler;ServerDemo server;server.setHandler(&handler);server.start(8888);return a.exec();
}

client.h

#ifndef CLIENTDEMO_H
#define CLIENTDEMO_H#include <QObject>
#include <QTcpSocket>
#include "TextMessage.h"
#include "txtmsgassembler.h"
#include "TxtMsgHandler.h"class ClientDemo : public QObject
{Q_OBJECTQTcpSocket m_client;            //客户端对象TxtMsgAssembler m_assembler;    //协议消息装配器TxtMsgHandler* m_handler;       //接口函数
protected slots:void onConnected();             //连接事件槽函数void onDisconnected();          //断连事件槽函数void onDataReady();             //消息事件槽函数void onBytesWritten(qint64 bytes);public:ClientDemo(QObject* parent = NULL);bool connectTo(QString ip, int port);   //连接服务器qint64 send(TextMessage& message);      //发送协议消息qint64 available();                     //查看缓冲区数据个数void setHandler(TxtMsgHandler* handler);bool isValid();                         //判断客户端状态void close();                           //关闭客户端
};#endif // CLIENTDEMO_H

client.cpp

#include "ClientDemo.h"
#include <QHostAddress>
#include <QDebug>//信号与槽的映射
ClientDemo::ClientDemo(QObject* parent) : QObject(parent), m_handler(nullptr)
{connect(&m_client, SIGNAL(connected()), this, SLOT(onConnected()));connect(&m_client, SIGNAL(disconnected()), this, SLOT(onDisconnected()));connect(&m_client, SIGNAL(readyRead()), this, SLOT(onDataReady()));connect(&m_client, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
}//连接信号的槽函数
void ClientDemo::onConnected()
{if( m_handler != nullptr ){TextMessage conn("CONN", m_client.peerAddress().toString() + ":" + QString::number(m_client.peerPort()));m_handler->handle(m_client, conn);}
}//断开连接的槽函数
void ClientDemo::onDisconnected()
{m_assembler.reset();    //重置装配类对象if( m_handler != nullptr ){TextMessage dscn("DSCN", "");m_handler->handle(m_client, dscn);}
}//接收数据的槽函数
void ClientDemo::onDataReady()
{char buf[256] = {0};int len = 0;//循环读取缓冲区中的字节流数据while( (len = m_client.read(buf, sizeof(buf))) > 0 ){QSharedPointer<TextMessage> ptm = nullptr;m_assembler.prepare(buf, len);  //加入存储容器while( (ptm = m_assembler.assemble()) != nullptr )//循环装配协议文本,直到没有文本可以装配{if( m_handler != nullptr ){m_handler->handle(m_client, *ptm);}}}
}void ClientDemo::onBytesWritten(qint64 bytes)
{(void)bytes;
}//同步的方式连接服务端
bool ClientDemo::connectTo(QString ip, int port)
{m_client.connectToHost(ip, port);return m_client.waitForConnected();
}//以协议消息为单位发送数据
qint64 ClientDemo::send(TextMessage& message)
{QByteArray ba = message.serialize();return m_client.write(ba.data(), ba.length());
}//查看缓冲区的数据长度
qint64 ClientDemo::available()
{return m_client.bytesAvailable();
}void ClientDemo::setHandler(TxtMsgHandler *handler)
{m_handler = handler;
}//查看客户端状态
bool ClientDemo::isValid()
{return m_client.isValid();
}//关闭客户端
void ClientDemo::close()
{m_client.close();
}

client_main.cpp

#include "MainwinUI.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWin w;w.show();return a.exec();
}

阶段性效果图

在这里插入图片描述

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

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

相关文章

Netty

目录 引言&#xff1a; 什么是Netty&#xff1f; Netty和Tomcat有什么区别&#xff1f; 为什么Netty受欢迎&#xff1f; Netty为什么并发高 Netty为什么传输快 为什么说Netty封装好&#xff1f; 使用示例&#xff1a; 步骤1: 添加Netty依赖 步骤2: 创建服务器启动类 步…

【JavaEE】_构造HTTP请求与HTTPS

目录 1. 构造HTTP请求 1.1 form标签构造HTTP请求 1.1.1 form标签构造GET请求 1.1.2 form标签构造POST请求 1.2 通过ajax构造HTTP请求 1.3 form与ajax 1.4 使用ajax构造HTTP请求 2.HTTPS 2.1 对称加密 2.2 非对称加密 2.3 证书 1. 构造HTTP请求 1.1 form标签构造HTT…

idea插件(free mybatis plugin)

安装&#xff1a; 由于我用的idea版本是2023的&#xff0c;所以搜出来的是Free MyBatis Tool,和Free MyBatis plugin是一样的 主要功能&#xff1a; 生成mapper xml文件 快速从代码跳转到mapper及从mapper返回代码 mybatis自动补全及语法错误提示 集成mybatis generator gui…

Spring Boot中的@Controller使用教程

一 Controller使用方法&#xff0c;如下所示&#xff1a; Controller是SpringBoot里最基本的组件&#xff0c;他的作用是把用户提交来的请求通过对URL的匹配&#xff0c;分配个不同的接收器&#xff0c;再进行处理&#xff0c;然后向用户返回结果。下面通过本文给大家介绍Spr…

JavaScript系列从入门到精通系列第十七篇:JavaScript中的全局作用域

文章目录 前言 1&#xff1a;什么叫作用域 一&#xff1a;全局作用域 1&#xff1a;全局变量的声明 2&#xff1a;变量声明和使用的顺序 3&#xff1a;方法声明和使用的顺序 前言 1&#xff1a;什么叫作用域 可以起作用的范围 function fun(){var a 1; } fun();consol…

Linux YUM源(本地/网络源)配置详解

目录 一、挂载 二、实现思路 三、建立本地源 配置详解&#xff1a; 四、建立网络源 配置详解&#xff1a; 五、验证 一、挂载 ——将光盘挂载到 /mnt ——挂载光盘时要保证虚拟机光盘处于连接状态 命令&#xff1a;[rootlocalhost mnt]# mount /dev/sr0 /mnt # 此时还…

MongoDB数据库网站网页实例-编程语言Python+Django

程序示例精选 PythonDjangoMongoDB数据库网站网页实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《PythonDjangoMongoDB数据库网站网页实例》编写代码&#xff0c;代码整洁&#xff0c;…

海信电视U8发布,一场针对画质的“定向跨越”

作者 | 曾响铃 文 | 响铃说 最近在重温《西游记》时&#xff0c;我才发现“灵性”这个东西有多讨喜。 在灵台方寸山&#xff0c;孙悟空头上被铛铛铛敲了三下&#xff0c;就悟出了师傅要为其深夜传授妙法&#xff0c;而这样的“感知”和“觉悟”&#xff0c;却在进修了那么多…

次方计数的拆贡献法(考虑组合意义)+限定类问题善用值域与位置进行ds:1006T3

对于多次方的计数问题可以考虑拆贡献。 题目问 ∣ S ∣ 3 |S|^3 ∣S∣3&#xff0c; ∣ S ∣ |S| ∣S∣ 表示选的点数。相当于在 ∣ S ∣ |S| ∣S∣ 中选了3次&#xff0c;也就是选了3个可相同的点。 先考虑3个不相同点的贡献&#xff0c;对应任意3个点&#xff0c;必然会对…

Flow Chart 的中文意思是什么?请说出自然界中河流的三种流动方式。事件驱动是什么?

目录 Flow Chart 的中文意思是什么? 请说出自然界中河流的三种流动方式。 事件驱动是什么? 请介绍一下 亚特兰大这座城市 Flow Chart 的中文意思是什么? 流程图 请说出自然界中河流的三种流动方式。 自然界中的河流可以以多种不同的方式流动&#xff0c;以下是其中三…

在Linux中软链接和硬链接的区别是什么?

2023年10月6日&#xff0c;周五晚上 目录 软链接(SymbolicLink):硬链接(HardLink):区别: 软链接(SymbolicLink): 软链接本身只是一个指向其他文件或目录的指针,不占用任何磁盘空间。软链接的修改或删除不会影响原文件。软链接可以指向不同文件系统中的文件。 硬链接(HardLink…

c++运算符重载实现

#include <iostream> #include <cstring> using namespace std; class myString { private:char *str;int size; public://无参构造myString():size(10){str new char[size]; //构造出一个长度为10的字符串strcpy(str,""); //赋值为空串}//有…

微信小程序开发缺少中间证书问题(腾讯云、阿里云等做服务器)

项目使用nginx做负载均衡后&#xff0c;不再采用原来直接用jar包的方式直接开启对应端口&#xff0c;所以需要重新从云服务器上下载证书&#xff0c;写入到Nginx读取的证书路径上即可。

stm32之HAL库操作PAJ75620

一、模块简介 手势模块PAJ7620主要利用IIC或SPI协议来实现数据的传输&#xff0c;本实验用的模块是以IIC来进行信息传输。支持电压从2.8v到3.6v, 正常可以选择3.3v。检测的距离从5到15cm, 可以检测9种手势&#xff0c;包括 右&#xff1a;编码为 0x01左&#xff1a;编码为 0x0…

[GXYCTF2019]禁止套娃 无回显 RCE 过滤__FILE__ dirname等

扫除git 通过githack 获取index.php <?php include "flag.php"; echo "flag在哪里呢&#xff1f;<br>"; if(isset($_GET[exp])){if (!preg_match(/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i, $_GET[exp])) {if(; preg_replace(/[a-z,_]\(…

redis实战-实现用户签到UV统计

BitMap功能演示 我们针对签到功能完全可以通过mysql来完成&#xff0c;比如说以下这张表 用户一次签到&#xff0c;就是一条记录&#xff0c;假如有1000万用户&#xff0c;平均每人每年签到次数为10次&#xff0c;则这张表一年的数据量为 1亿条 每签到一次需要使用&#xff08…

支付环境安全漏洞介绍

1、平台支付逻辑全流程分析 2、平台支付漏洞如何利用&#xff1f;买东西还送钱&#xff1f; 3、BURP抓包分析修改支付金额&#xff0c;伪造交易状态&#xff1f; 4、修改购物车参数实现底价购买商品 5、SRC、CTF、HW项目月入10W副业之路 6、如何构建最适合自己的网安学习路线 1…

ArcGIS Engine:鹰眼图的拓展功能-点击和矩形+坐标状态栏

目录 01 前言 02 鹰眼图的控制功能 03 显示当前鼠标的地理坐标 01 前言 说是拓展&#xff0c;不过是忘记了实验还有附加实验.这里补上. 前文不再赘述,上一节查看&#xff1a;ArcGIS Engine&#xff1a;视图菜单的创建和鹰眼图的实现_炒茄子的博客-CSDN博客 这里加上三个功能…

elementui修改message消息提示颜色

/* el弹出框样式 */ .el-message {top: 80px !important;border: 0; }.el-message * {color: var(--white) !important;font-weight: 600; }.el-message--success {background: var(--themeBackground); }.el-message--warning {background: var(--gradientBG); }.el-message--…

最强中间件!Kafka快速入门(Kafka理论+SpringBoot集成Kafka实践)

自媒体文章上下架 需求分析 媒体端下架文章同时app端也下架文章的实现可以通过feign去调用&#xff0c;但这种实现耦合度太高&#xff0c;这里使用MQ进行解耦 自媒体端一旦上下架文章就发送消息给MQ&#xff0c;文章微服务在去读取消息根据消息内容上下架文章 MQ还可以流量削…