第五天项目日记

1、今日总结

今天完成客户端第一个界面的编写
客户端的注册、登录 发送账号密码的消息使用json格式

2、设计思路

主要操作数据库,以及一些消息的定义,由于客户端的socket再另一个线程里面,所以接收消息的工作都放在客户端的socket线程,ui的显示由线程发送信号给weidget

3、代码说明

3.1 服务器主要修改代码

dbhelper.h

新增登录和注册判断

dbhelper.cpp

QString dbhelper::logic_judge(QString name, QString pswd)
{QSqlQuery query(*db);query.prepare("select * from user where name = :name");//用来绑定值query.bindValue(":name",name);bool res = query.exec();if(!res){qDebug()<<query.lastQuery();}while(query.next()){QString _name = query.value("name").toString();QString _pswd = query.value("pswd").toString();if(_name == name){if(pswd == _pswd){return "success";}else{return "pswd_error";}}}if(!res){//用来打印错误信息qDebug()<<query.lastError().text();}return "no_name";
}QString dbhelper::user_reg(QString name, QString pswd)
{QSqlQuery query(*db);//先看一下名字有没有query.prepare("select * from user where name = :name");query.bindValue(":name",name);bool res = query.exec();if(!res){qDebug()<<query.lastError().text();qDebug()<<query.lastQuery();}qDebug()<<"size = "<<query.size();if(query.next()){return "rename";//名字重复}query.prepare("insert into user (name,pswd) values (:name,:pswd)");query.bindValue(":name",name);query.bindValue(":pswd",pswd);res = query.exec();if(!res){qDebug()<<query.lastQuery();}return "success";
}

message.h

修改msg的枚举

增加了函数接口

tcpsocket.h

void TcpSocket::msgPrase(QString msg_buf)
{int item;QString buf;buf.clear();item = msg_buf.section('|',0,0).trimmed().toInt();int item_len = QString::number(item).length();qDebug()<<"len"<<item_len;buf = msg_buf.right(msg_buf.length()-item_len-1);qDebug()<<"item"<<item<<" "<<buf;//把它转换成消息发送给serverMyMessage message((MsgId)item,buf,buf.length());if(message.isInEnum()){if(message.getmsgid() == MSG_CLIENT_CLOSE || message.getmsgid() == MSG_CLITEN_CONNECT){emit messageToServer(message); //发射消息信号}else if(message.getmsgid() == MSG_LOGIC){message.setmsgbuf(prase_MSG_LOGIC(message.getmsgbuf()));this->write(message.toString().toLatin1(),message.toString().length());}else if(message.getmsgid() == MSG_REGISTER){message.setmsgbuf(prase_MSG_REG(message.getmsgbuf()));this->write(message.toString().toLatin1(),message.toString().length());}else if(message.getmsgid() == MSG_SHAKE_HAND){message.setmsgbuf(" ");this->write(message.toString().toLatin1(),message.toString().length());}}else{qDebug()<<"无效数据";}
}QString TcpSocket::prase_MSG_LOGIC(QString message_buf)
{QByteArray bytes = message_buf.toUtf8();QJsonParseError jsonError;QString name;QString pswd;QJsonDocument doucment = QJsonDocument::fromJson(bytes, &jsonError);if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {  // 解析未发生错误if (doucment.isObject()){QJsonObject object = doucment.object();  // 转化为对象if (object.contains("Name")) {QJsonValue value = object.value("Name");if (value.isString()) {name = value.toString();qDebug() << "Name : " << name;}}else{return "json_error_no_name";}if (object.contains("password")) {QJsonValue value = object.value("password");if (value.isString()) {pswd = value.toString();qDebug() << "pswd : " << pswd;}}else{return "json_error_no_pswd";}}else{return "json is no object";}}else{return "json error";}return mydb->logic_judge(name,pswd);
}QString TcpSocket::prase_MSG_REG(QString message_buf)
{qDebug()<<message_buf;QByteArray bytes = message_buf.toUtf8();QJsonParseError jsonError;QString name;QString pswd;QJsonDocument doucment = QJsonDocument::fromJson(bytes, &jsonError);if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {  // 解析未发生错误if (doucment.isObject()){QJsonObject object = doucment.object();  // 转化为对象if (object.contains("Name")) {QJsonValue value = object.value("Name");if (value.isString()) {name = value.toString();qDebug() << "Name : " << name;}}else{return "json_error_no_name";}if (object.contains("password")) {QJsonValue value = object.value("password");if (value.isString()) {pswd = value.toString();qDebug() << "pswd : " << pswd;}}else{return "json_error_no_pswd";}}else{return "json is no object";}}else{return "json error";}return mydb->user_reg(name,pswd);
}

3.2客户端修改部分

连接的时候根据状态变化发送信号
登录的时候发送登录信号
注册的时候发送注册信号
直接转发收到的字符串
然后在主函数中判断

tcpthread.h

#ifndef TCPTHREAD_H
#define TCPTHREAD_H#include <QObject>
#include <QTcpSocket>
#include <QThread>
#include <QDebug>
#include "mymessage.h"class TcpThread : public QThread
{Q_OBJECT
public:explicit TcpThread(QObject *parent = 0);~TcpThread();void startThread(const QString& ip, int port);void stopThread();void onSendTcp(QString);void parse_msg(QString);signals:void send_tcpmsg(QString);void send_logic_msg(QString);void send_reg_msg(QString);public:int m_iSendData;int m_iRecv_TimeOut;int reconnect_num;private:QTcpSocket* m_TcpSocket;bool        m_isThreaStopped;bool       m_isOkConect;QString    m_QStrSocketIp;int      m_nSockPort;QByteArray  m_datagram;protected:virtual void run();private slots:void onConnect();void onDisConnect();void onReadMsg();public slots:
};#endif // TCPTHREAD_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QMessageBox>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include "tcpthread.h"
#include "mymessage.h"namespace Ui {class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();void Logic_Init();//登录初始化void User_Init();//使用界面初始化void connectToServer(); //用连接服务器public slots:void connect_state(QString); //用来控制连接状态void connect_success(); //用来判断连接状态void logic_msg_recv(QString); //用来处理登录消息void reg_msg_recv(QString); //用来处理注册消息private slots:void on_radioshow_clicked(bool checked); //用来显示密码和隐藏密码void on_pushlogic_clicked();//用来登录void on_pushquit_clicked();//用来退出void on_pushregister_clicked();signals:void connect_enable(); //连接private:Ui::Widget *ui;TcpThread *tcpThread;//用来启动socket线程
//    bool status;QString userName; //账号QString passWord; //密码int Logic_Flag; //用来判断是登录还是注册0注册1登录};#endif // WIDGET_H

tcpthread.cpp

#include "tcpthread.h"TcpThread::TcpThread(QObject *parent) :QThread(parent)
{m_TcpSocket = nullptr ;m_isThreaStopped = false;m_isOkConect = false;reconnect_num = 0;
}TcpThread::~TcpThread()
{m_isThreaStopped = true;quit();wait();
}void TcpThread::startThread(const QString &ip, int port)
{m_QStrSocketIp = ip;m_nSockPort = port;m_isThreaStopped = false;start();
}void TcpThread::stopThread()
{reconnect_num = 0;m_isThreaStopped = true;
}void TcpThread::run()
{bool b_recv_flag = false;emit send_tcpmsg("connecting");if (!m_TcpSocket){m_TcpSocket = new QTcpSocket(this);connect(m_TcpSocket, SIGNAL(readyRead()), this, SLOT(onReadMsg()),Qt::DirectConnection);//让接受函数在run子线程中执行(发送者执行)connect(m_TcpSocket, SIGNAL(connected()), this, SLOT(onConnect()));connect(m_TcpSocket, SIGNAL(disconnected()), this, SLOT(onDisConnect()));}while (!m_isThreaStopped){//检测客户端 socket指针是否为空if(b_recv_flag)msleep(100);if (!m_isOkConect){// 终止当前连接并重置套接字(立即关闭套接字,丢弃写缓冲区中的任何挂起数据)m_TcpSocket->abort();m_TcpSocket->connectToHost(m_QStrSocketIp, m_nSockPort);//等待连接。。。延时三秒,三秒内连不上返回falsem_isOkConect = m_TcpSocket->waitForConnected(3000);m_iRecv_TimeOut = -1;reconnect_num++;}if (!m_isOkConect){msleep(1);if(reconnect_num <3){QString reconnect = "reconnect_"+QString::number(reconnect_num);emit send_tcpmsg(reconnect);continue;}else{emit send_tcpmsg("overtime");break;}}/*else{qDebug()<<"tcp_flag:"<<m_iRecv_TimeOut;QString msg_buf = " ";MyMessage msg_shake_hand(MSG_SHAKE_HAND,msg_buf,msg_buf.length());
//            onSendTcp(msg_shake_hand.toString());onSendTcp(msg_buf);}*/b_recv_flag = m_TcpSocket->waitForReadyRead(100);if  (b_recv_flag){m_iRecv_TimeOut = 0;}else{m_iRecv_TimeOut++;if(m_iRecv_TimeOut>150) m_iRecv_TimeOut=150;}if(m_iRecv_TimeOut >= 100){QString msg_buf = " ";MyMessage msg_shake_hand(MSG_SHAKE_HAND,msg_buf,msg_buf.length());onSendTcp(msg_shake_hand.toString());
//            onSendTcp(msg_buf);}if(m_iRecv_TimeOut >= 150){m_iRecv_TimeOut = -1;}}m_TcpSocket->disconnectFromHost();
}void TcpThread::onConnect()
{reconnect_num = 0;emit send_tcpmsg("connect");
}void TcpThread::onDisConnect()
{//socket一旦断开则自动进入这个槽函数//通过把 m_isOkConect 设为false,在socket线程的run函数中将会重新连接主机qDebug()<<"socket is disconnect!"<<endl;m_isOkConect = false;m_iRecv_TimeOut = -1;emit send_tcpmsg("disconnect");
}void TcpThread::onReadMsg()
{if(m_TcpSocket->bytesAvailable() <= 0){//  判定连接失败m_TcpSocket->disconnectFromHost();}while (m_TcpSocket->bytesAvailable() > 0){// 接收数据m_datagram.clear();m_datagram.resize(m_TcpSocket->bytesAvailable());m_TcpSocket->read(m_datagram.data(), m_datagram.size());QString str_tcp_receive = QString::fromLocal8Bit(m_datagram);parse_msg(str_tcp_receive);qDebug()<<str_tcp_receive;msleep(100);}
}void TcpThread::onSendTcp(QString str_info)
{if((!m_TcpSocket)||m_TcpSocket->state()!=QAbstractSocket::ConnectedState)return;m_iSendData = m_TcpSocket->write(str_info.toLatin1(), str_info.length());m_TcpSocket->flush();if (m_iSendData < 0){m_TcpSocket->disconnectFromHost();return;}msleep(1000);
}void TcpThread::parse_msg(QString msg_buf) //解析接收到的消息
{int item;QString buf;item = msg_buf.section('|',0,0).trimmed().toInt();int item_len = QString::number(item).length();buf = msg_buf.right(msg_buf.length()-item_len-1);if(item == (int)MSG_LOGIC){emit send_logic_msg(buf);//发送登录消息return;}else if(item == (int)MSG_REGISTER){emit send_reg_msg(buf);//发送注册消息return;}return;
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QThread>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);tcpThread = nullptr;//    status = false;Logic_Init();QObject::connect(this,SIGNAL(connect_enable()),this,SLOT(connect_success()));
}Widget::~Widget()
{delete ui;
}void Widget::Logic_Init()
{this->setWindowTitle("登录/注册");ui->linepswd->show();ui->lineUser->show();ui->radioshow->show();ui->pushlogic->show();ui->pushregister->show();ui->linepswd->setEchoMode(QLineEdit::Password);ui->pushAdd->hide();ui->pushCreate->hide();ui->listView->hide();ui->pushquit->hide();
}void Widget::User_Init()
{this->setWindowTitle("云木直播平台");ui->linepswd->hide();ui->lineUser->hide();ui->radioshow->hide();ui->pushlogic->hide();ui->pushregister->hide();ui->label->hide();ui->label_2->hide();ui->label_3->hide();ui->pushAdd->show();ui->pushCreate->show();ui->listView->show();ui->pushquit->show();
}void Widget::connectToServer()
{QString Address_Ip = "127.0.0.1";int port = 8010;if(!tcpThread){tcpThread = new TcpThread;QObject::connect(tcpThread,SIGNAL(send_tcpmsg(QString)),this,SLOT(connect_state(QString)));QObject::connect(tcpThread,SIGNAL(send_logic_msg(QString)),this,SLOT(logic_msg_recv(QString)));QObject::connect(tcpThread,SIGNAL(send_reg_msg(QString)),this,SLOT(reg_msg_recv(QString)));}tcpThread->startThread(Address_Ip,port);
}void Widget::connect_state(QString message)
{qDebug()<<message;if(message == "connecting") {ui->label_connect_state->setText("连接中...");}else if(message == "connect"){ui->label_connect_state->clear();emit connect_enable();return;}else if(message == "disconnect"){tcpThread->stopThread();return;}else if(message == "overtime"){QMessageBox::warning(NULL,tr("无法连接"),tr("无法连接请稍后再试"));ui->label_connect_state->clear();tcpThread->stopThread();return;}else if(message.left(9) == "reconnect"){QString text = "第"+message.right(1)+"次重连中";ui->label_connect_state->setText(text);}
}void Widget::connect_success()
{QJsonObject json;json.insert("Name",userName);json.insert("password",passWord);QJsonDocument document;document.setObject(json);QByteArray byteArray = document.toJson(QJsonDocument::Compact);QString strJson(byteArray);MyMessage mymsg((Logic_Flag?MSG_LOGIC:MSG_REGISTER),strJson,strJson.length());qDebug()<<mymsg.toString();tcpThread->onSendTcp(mymsg.toString());
}void Widget::logic_msg_recv(QString message)
{if(message == "success"){QMessageBox::about(NULL,"登录","登录成功");User_Init();return;}else if(message == "pswd_error"){QMessageBox::warning(NULL," 密码错误","密码输入错误请重试");tcpThread->stopThread();return;}else if(message == "no_name"){QMessageBox::warning(NULL,"未注册","请先注册账号");tcpThread->stopThread();return;}
}void Widget::reg_msg_recv(QString message)
{if(message == "success"){QMessageBox::about(NULL,"注册","注册成功");tcpThread->stopThread();return;}else if(message == "rename"){QMessageBox::warning(NULL,"用户名重复","请输入其他用户名");tcpThread->stopThread();}else{tcpThread->stopThread();}
}void Widget::on_radioshow_clicked(bool checked)
{if(checked){ui->linepswd->setEchoMode(QLineEdit::Normal);}else{ui->linepswd->setEchoMode(QLineEdit::Password);}
}void Widget::on_pushlogic_clicked()
{if(ui->lineUser->text().isEmpty()){QMessageBox::warning(NULL,tr("输入错误"),tr("账号不能为空"));return;}if(ui->linepswd->text().isEmpty()){QMessageBox::warning(NULL,tr("输入错误"),tr("密码不能为空"));return;}userName = ui->lineUser->text();passWord = ui->linepswd->text();Logic_Flag = 1;//连接connectToServer();
}void Widget::on_pushquit_clicked()
{tcpThread->stopThread();QMessageBox::about(NULL,tr("退出"),tr("点击退出"));this->close();
}void Widget::on_pushregister_clicked()
{if(ui->lineUser->text().isEmpty()){QMessageBox::warning(NULL,tr("输入错误"),tr("账号不能为空"));return;}if(ui->linepswd->text().isEmpty()){QMessageBox::warning(NULL,tr("输入错误"),tr("密码不能为空"));return;}userName = ui->lineUser->text();passWord = ui->linepswd->text();Logic_Flag = 0;//连接connectToServer();
}

4、项目文件

源代码文件.

5、效果展示

数据库中的用户如下

1、测试已有用户是否可以注册

2、测试未注册用户是否可以登录

3、测试未注册用户能否注册

4、测试已有用户密码以及能否登录成功

这里服务器用户列表会显示是因为只要建立了连接就会显示,后面会改掉

6、小结

使用了一些QJson

坚持就是胜利!!!!!!

Qt视频直播软件--项目实战(Day5)相关推荐

  1. 不一样的短视频直播软件开发?

    在短视频行业中,短视频直播app软件中抖音是最为经典的案例,随着目前视频行业的爆发式增长,他很快的成为用户拍摄短视频的首选,如果说有什么项目最火,我想应该是微视了,以前的快手,现在的抖音,反正我没事的 ...

  2. 视频直播软件开发中关于极光用户修改 [头像、昵称] 的教程

    视频直播软件开发中一定会用到推送或IM即时通讯,但是正常情况下更新用户信息只会更新数据库的信息,并不会同步更新到服务器,那么接下来我们就以极光为例,讲述该如何修改用户头像及昵称.基本步骤如下: 1.上 ...

  3. 视频直播软件开发关于亚马逊s3接入方式,视频直播源码创建存储桶方法

    一.登录亚马逊账户,进入S3 建立新的存储桶,用于视频直播源码的文件存储. 注册 Amazon S3 后,您就可以开始使用 AWS 管理控制台 创建存储桶.Amazon S3 中的每个对象都存储在存储 ...

  4. 视频直播软件开发过程中需要解决的“老朋友”...

    要说在视频直播软件开发的过程中,什么是技术人员最头疼的?肯定有人会毫无疑问的回答:直播的卡顿和延时!没错,这两位可以说是直播中的"老朋友"了.毫不夸张的说,每一个直播平台都遇到过这 ...

  5. 如何评判在线直播源码优劣?视频直播软件开发经验之谈

    直播经过这些年的不断发展,使用者逐渐增加,在视频直播软件开发行业从业者的不断努力下,在线直播源码变得越来越完善,甚至已有了一些开发窍门的积累和判断视频直播软件优劣性的指标,本篇文章就来讲讲,该如何评判 ...

  6. 一对一直播源码 一对一视频直播软件未来发展趋势

    一对一视频直播软件对比传统直播平台,直播方式更简单自由,同时也更加私密,比传统直播平台更能保护用户私密,又能增加主播与用户之间的互动. 一对一视频直播的方式颠覆了人们对传统直播的看法,一对一直播凭借高 ...

  7. 视频直播软件未来发展的方向有哪些

    现在使用视频直播软件的人群非常多,很多人把把它当成是一种娱乐的方式,很多人可以一起参与进去,不受距离的影响,就像面对面可以看到影像和听到声音,可以进行互相的交流,或者是做游戏等等.将来他还会有更多的发 ...

  8. 目前国内p2p视频直播软件

    目前国内p2p视频直播软件  名称  官方网址  评价[来自于http://family.chinaok.com/2005-12/15338.htm]    synacast  http://www. ...

  9. 在视频直播软件开发中,这样做才能实现svga格式礼物动画

    在线直播源码中,礼物功能的开发是必不可少的,它不但可以作为用户对主播的喜爱度的评判标准,还是直播平台变现的方式之一,那么在直播源码中,svga格式礼物动画是如何实现的呢?以云豹的金山demo为例,实现 ...

  10. 【网络通信 -- 直播】项目实战记录 -- 弱网模拟工具

    [网络通信 -- 直播]项目实战记录 -- 弱网模拟工具 [1]Windows 系统中弱网模拟工具 Windows 系统中可以使用 Clumsy 工具模拟弱网环境 Lag(延迟),把数据包缓存一段时间 ...

最新文章

  1. mysql 评论回复表设计_【数据库】评论回复表设计
  2. 拨云见日—深入解析Oracle TX 行锁(上)
  3. VMWare 安装 Eclipse
  4. 数据库原理及应用【三】DBMS+SQL
  5. C++学习之路 | PTA乙级—— 1040 有几个PAT (25 分)(精简)
  6. 通过一个例子来理解二维码纠错机制
  7. JavaScript性能优化【中】-- Performance 工具
  8. ODP.NET数据访问
  9. curl: (48) An unknown option was passed in to libcurl
  10. linux在路径下创建文件,从可以在Linux中打开的文件路径创建文件
  11. idc机房安装服务器系统,IDC机房如何部署IP KVM
  12. # 研究杂感 × VOSviewer(第五辑)
  13. 自由曲面透镜设计matlab,实现LED台灯均匀照明的自由曲面透镜仿真设计
  14. 数据库导出数据字典(MySQL)
  15. 高仿淘宝商品商品上拉加载SlideDetailsLayout+viewPager事件冲突
  16. Pairwise 找到你的另一半
  17. 全球与中国保健品OEM和ODM市场现状调查及投资规划建议报告2022-2028年
  18. Jmeter进行上传图片接口测试
  19. 天水市师院计算机系好吗,天水师范学院专业排名及介绍 哪些专业最好
  20. 图:两点之间的最短距离

热门文章

  1. 关于VGGNet网络结构浅谈(主要是VGG16结构)
  2. 【java】输入输出流
  3. 来自TMDB的5000部电影数据集
  4. 阿里云短信SDK使用
  5. java 自定义进度条_JAVA Swing 自定义进度条样式(简单实现)
  6. 程序员音乐_预订音乐会的程序员指南
  7. 电子科技大学《图论及其应用》复习总结--第一章 图的基本概念
  8. 琴生Jensen不等式,条件期望
  9. 计算机控制技术微课,课程名称:微型计算机控制技术课程
  10. Vue后台管理系统项目总结