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

这篇具有很好参考价值的文章主要介绍了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_OBJECT

    QTcpServer 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_OBJECT

    QTcpSocket 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();
}

阶段性效果图

QT聊天室阶段性记录(完善中:注册功能,数据库存储),qt文章来源地址https://www.toymoban.com/news/detail-728316.html

到了这里,关于QT聊天室阶段性记录(完善中:注册功能,数据库存储)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 阶段性复习 迭代器, Lambda表达式, 泛型, 单例模式

        迭代器(Iterator)是一种设计模式,用于顺序访问集合中的元素,而不需要了解集合内部的结构。     迭代器模式将元素的遍历行为和集合类解耦,使得可以在不修改集合类的情况下遍历集合。     具体来说,一个迭代器对象包含了遍历集合所需的状态信息,如当前遍

    2024年02月11日
    浏览(23)
  • Qt项目网络聊天室设计

    效果演示 网络聊天室 网络聊天室程序 基于TCP的可靠连接 (QTcpServer、QTcpSocket) 一个服务器,多个客户端   3. 服务器接收到某个客户端的请求以及发送信息,经服务器发给其它客户端 最终实现一个 共享聊天内容的聊天室! QTcpServer 提供一个TCP基础服务类 继承自QObject,这个类

    2024年02月10日
    浏览(32)
  • qt服务器 网络聊天室

    widget.cpp  

    2024年02月15日
    浏览(28)
  • Java+Vue实现聊天室(WebSocket进阶-聊天记录)

    WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服

    2024年02月11日
    浏览(35)
  • 单晶高温合金收获阶段性应用成果,科研人员已开展定向凝固实验

    根据央视报道,中国科学院金属研究所的科研人员对从太空带回的铝硅合金样品进行了初步的解剖分析工作,并计划用不同的实验方法和合金材料继续开展相关实验工作,以进一步探索重力在单晶高温合金凝固过程中的具体作用及相关机理。 值得关注的是,单晶高温合金作为

    2024年02月12日
    浏览(24)
  • 基于qt软件的网上聊天室软件

    1.服务器:         1).功能: 用于创建一个客户端,通过文本编辑器来获得端口号,根据获得的端口号创建服务器,等待客户端连接 创建成功会提示服务器创建成功 在收到客户端发送的信息时,把这条信息发送给其他所有客户端,实现群聊功能         2).代码: 2.客户端

    2024年02月09日
    浏览(31)
  • Qt实战:云曦聊天室篇——环境部署

    基于Qt的网络聊天室,可进行群聊,私聊,添加好友,创建群聊,添加群聊等功能

    2024年02月05日
    浏览(20)
  • SpringBoot与webSocket实现在线聊天室——实现私聊+群聊+聊天记录保存

    引用参考:原文章地址:https://blog.csdn.net/qq_41463655/article/details/92410518 在此基础上实现对聊天记录的保存。 代码地址:链接:https://pan.baidu.com/s/1IJFZDa4S_DF08773sKJWeA 提取码:jkui 思路:新建一个实体类用于保存聊天记录,在消息发送时,设置对象的各个值然后保存到数据库中。

    2024年02月02日
    浏览(34)
  • 20230904 QT客户端服务器搭建聊天室

    Ser Cli

    2024年02月09日
    浏览(29)
  • QT C++ 基于TCP通信的网络聊天室

    .ui .pro 在pro文件中添加network库 .h .main .cpp .ui .pro 在pro文件中添加network库 .h .main .cpp        

    2024年02月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包