阅读量:0
一、设计要求
用QT做一个聊天室,
制作一个服务器和客户端。可以进行注册、登录,
登陆成功后可以使用昵称进行发送、接收消息。
能根据昵称、聊天内容查询历史记录,也可以查询全部聊天记录。
。
二、客户端三级ui界面
三、项目代码
//在pro文件里加入 QT += core gui network RC_FILE += icon_config.rc
//客户端dialog.h #ifndef DIALOG_H #define DIALOG_H #include <QtWidgets> #include <QDebug> // 网络连接类 #include <QTcpSocket> // 文本流 #include <QTextStream> #include <QDateTime> #include <QByteArray> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); private: Ui::Dialog *ui; QTcpSocket *client; void printMsg(QString); // 输出内容到公屏 void succRight(); private slots: void btnConnClickedSlot(); // 连接按钮 void btnSendClickedSlot(); // 发送按钮 void connectedSlot(); // 连接成功的槽函数 void disconnectedSlot(); // 断开连接的槽函数 void readReadSlot(); // 接收数据的槽函数 void btnHisClickedSlot();//历史记录 void btnHisNameClickedSlot();//按照昵称 void btnHisNeiClickedSlot();//按照内容 void btnLoginClickedSlot();//登录/切换窗口 void btnRegClickedSlot();//注册 }; #endif // DIALOG_H
//客户端dialog.c #include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); // 抢前台 setWindowFlags(Qt::WindowStaysOnTopHint); connect(ui->pushButtonConn,SIGNAL(clicked()), this,SLOT(btnConnClickedSlot())); connect(ui->pushButtonSend,SIGNAL(clicked()), this,SLOT(btnSendClickedSlot())); client = new QTcpSocket(this); // 建立网络连接检测的信号槽 connect(client,SIGNAL(connected()), this,SLOT(connectedSlot())); connect(client,SIGNAL(disconnected()), this,SLOT(disconnectedSlot())); // 接收消息的信号槽 connect(client,SIGNAL(readyRead()), this,SLOT(readReadSlot())); //历史 connect(ui->pushButtonHis,SIGNAL(clicked()), this,SLOT(btnHisClickedSlot())); connect(ui->pushButtonName,SIGNAL(clicked()), this,SLOT(btnHisNameClickedSlot())); connect(ui->pushButtonNei,SIGNAL(clicked()), this,SLOT(btnHisNeiClickedSlot())); //切换窗口:登录 connect(ui->pushButtonLo,SIGNAL(clicked()), this,SLOT(btnLoginClickedSlot())); //注册 connect(ui->pushButtonReg,SIGNAL(clicked()), this,SLOT(btnRegClickedSlot())); } Dialog::~Dialog() { disconnect(client,SIGNAL(disconnected()), this,SLOT(disconnectedSlot())); // 如果还在连接 if(client->isOpen()) client->close(); delete ui; } void Dialog::btnConnClickedSlot() { // 发起连接请求 // 默认用户输入的参数都对 client->connectToHost(ui->lineEditIp->text(),ui->spinBox->value()); } void Dialog::printMsg(QString msg) { // 获得当前时间 QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"); ui->textBrowser->append(time); ui->textBrowser->append(msg); ui->textBrowser->append(""); } void Dialog::succRight() { ui->stackedWidget->setCurrentIndex(1); } void Dialog::btnSendClickedSlot() { // 获得昵称和消息内容 QString user = ui->lineEditUser->text(); if(user=="") { QMessageBox::warning(this,"提示","请输入昵称!"); return; } QString msg = ui->lineEditMsg->text(); if(msg == "") { QMessageBox::warning(this,"提示","请输入要发送的消息!"); return; } QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss"); // 创建文本流对象 QTextStream output(client); // 连续输出发送 output << time<<":"<<user << ":" << msg; // 清空消息输入框 ui->lineEditMsg->clear(); // 公屏显示 msg = user+QString("(本机):")+msg; printMsg(msg); } void Dialog::connectedSlot() { // 屏蔽连接按钮,开启发送按钮 ui->pushButtonConn->setEnabled(false); ui->pushButtonConn->setText("已连接"); ui->pushButtonSend->setEnabled(true); ui->stackedWidget->setCurrentIndex(1); } void Dialog::readReadSlot() { QTextStream input(client); QString text = input.readAll(); QString text1=input.readLine(100); qDebug() <<text1; QStringList list = text.split(":"); QStringList list2 = text1.split(":"); qDebug()<<"分割后数量"<<list.size(); qDebug() <<list2.size(); if(list.size()<4) { if(text=="dlchengg") { qDebug() <<text; ui->stackedWidget->setCurrentIndex(2); ui->textBrowser->clear(); } // else if(list.size()==3) // { // ui->textBrowser_2->append(text); // return; // } else { printMsg(text); } } else if(list.size()>=4) { ui->textBrowser_2->append(text); return; } } void Dialog::btnHisClickedSlot() { ui->textBrowser_2->clear(); QString user = ui->lineEditUser->text(); if(user=="") { QMessageBox::warning(this,"提示","请输入昵称!"); return; } QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss"); // 创建文本流对象 QTextStream output(client); QString mm="历史记录"; output<< time<<":"<<user << ":" <<mm ; } void Dialog::btnHisNameClickedSlot() { ui->textBrowser_2->clear(); QString user = ui->lineEditUser->text(); QString time = "hh"; // 创建文本流对象 QTextStream output(client); QString mm="按照昵称"; output<< time<<":"<<user << ":" <<mm ; } void Dialog::btnHisNeiClickedSlot() { ui->textBrowser_2->clear(); QString user = "sjdhs"; QString time = "按照内容"; // 创建文本流对象 QString msg = ui->lineEditMsg->text(); if(msg == "") { QMessageBox::warning(this,"提示","请输入要发送的消息!"); return; } QTextStream output(client); output<< time<<":"<<user << ":" <<msg ; } void Dialog::btnLoginClickedSlot() { QString user = ui->lineEditUs->text(); if(user=="") { QMessageBox::warning(this,"提示","请输入昵称!"); return; } QString pwd = ui->lineEdit_2Pwd->text(); if(pwd == "") { QMessageBox::warning(this,"提示","请输入密码!"); return; } // 创建文本流对象 QTextStream output(client); // 连续输出发送 QString mag="hha"; QString haf="lele"; output <<user << ":" << pwd<<":"<<mag<<":"<<haf; } void Dialog::btnRegClickedSlot() { QString user = ui->lineEditUs->text(); if(user=="") { QMessageBox::warning(this,"提示","请输入昵称!"); return; } QString pwd = ui->lineEdit_2Pwd->text(); if(pwd == "") { QMessageBox::warning(this,"提示","请输入密码!"); return; } // 创建文本流对象 QTextStream output(client); // 连续输出发送 output <<user << ":" << pwd; } void Dialog::disconnectedSlot() { // 开启连接按钮,屏蔽发送按钮 ui->pushButtonConn->setEnabled(true); ui->pushButtonConn->setText("连接"); ui->pushButtonSend->setEnabled(false); // 弹窗 printMsg("连接已断开!"); QMessageBox::warning(this,"提示","连接已断开!"); ui->stackedWidget->setCurrentIndex(0); }
//服务器dialog.h #ifndef DIALOG_H #define DIALOG_H #include <QtWidgets> #include <QDebug> // 连接管理类 #include <QTcpServer> #include <QDateTime> // 连接类 #include <QTcpSocket> // 文本流 #include <QTextStream> #include <QButtonGroup> #include <QSqlDatabase> #include <QDebug> #include <QSqlError> #include <QMessageBox> #include <QSqlQuery> #include <QByteArray> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); private: Ui::Dialog *ui; QTcpServer* server; // 管理对象(母鸡) void printMsg(QString); // 输出内容到公屏 QTcpSocket* socket = NULL; // 连接对象(绿蛋) QList<QTcpSocket*> sockets; QList<QString> ips; QSqlDatabase db; void connect2DB(); // 连接到数据库1 void createTable();// 建表 void createTable2(); void insertData(); // 插入数据 void selectAll(int); // 数据全查 void selectLOgin(QString,QString,int); void selectName(QString,int); void selectNei(QString,int); private slots: // 新连接来了的槽函数 void newConnSlot(); // 连接掉线的信号槽 void disconnetedSlot(); // 有数据可读时的槽函数 void readyReadSlot(); }; #endif // DIALOG_H
//服务器dialog.c #include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); // 抢前台 setWindowFlags(Qt::WindowStaysOnTopHint); server = new QTcpServer(this); // 连接新连接来了的信号槽 connect(server,SIGNAL(newConnection()), this,SLOT(newConnSlot())); // 开启监听服务 server->listen(QHostAddress::Any,8887); connect2DB(); } Dialog::~Dialog() { if(server->isListening()) // 如果还在监听 server->close(); delete ui; } void Dialog::printMsg(QString msg) { // 获得当前时间 QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); ui->textBrowser->append(time); ui->textBrowser->append(msg); ui->textBrowser->append(""); } void Dialog::connect2DB() { // 创建连接对象 db = QSqlDatabase::addDatabase("QSQLITE"); // 设置数据库的文件名称 db.setDatabaseName("book_management.db"); // 打开数据库 if(db.open()) { qDebug() << "连接成功"; // createTable(); // createTable2(); } else { // 获得错误信息封装类 QSqlError info = db.lastError(); // 提取错误文本 QString text = info.text(); // 展示错误 QMessageBox::critical(this,"错误",text); } } void Dialog::createTable() { QString sql = "CREATE TABLE book(time TEXT PRIMARY KEY,name TEXT,msg TEXT);"; // 创建数据库操作类对象 QSqlQuery sq; if(sq.exec(sql)) { qDebug() << "建表成功"; }else// 失败 { // 获得错误信息封装类 QSqlError info = sq.lastError(); // 提取错误文本 QString text = info.text(); // 展示错误 qDebug() << text; } } void Dialog::createTable2() { QString sql2 = "CREATE TABLE class(name TEXT PRIMARY KEY,pwd TEXT);"; // 创建数据库操作类对象 QSqlQuery sq; if(sq.exec(sql2)) { qDebug() << "建表2成功"; }else// 失败 { // 获得错误信息封装类 QSqlError info = sq.lastError(); // 提取错误文本 QString text = info.text(); // 展示错误 qDebug() << text; } } void Dialog::selectAll(int i) { QString sql = "SELECT * FROM book"; QSqlQuery sq; sq.prepare(sql); if(sq.exec(sql)) { // 清空上次显示 // ui->textBrowser->clear(); while(sq.next())// 循环取出 { // 取出一条数据库中的字段 QString time = sq.value(0).toString(); QString name = sq.value(1).toString(); QString msg = sq.value(2).toString(); QString msa="历史"; // 拼接并显示 QString text = msa.append(":")+ time.append(":")+ name.append(":") + msg; QTextStream output(sockets.at(i)); output<< text<<endl; } } } void Dialog::selectLOgin(QString user, QString pwd2,int i) { QString name=user; QString pwd=pwd2; QString sql = "SELECT * FROM class WHERE name LIKE ? AND pwd LIKE ?;"; QSqlQuery sq; sq.prepare(sql); if(sq.exec(sql)) { while(sq.next()) { qDebug() << "yes"; QString user = sq.value(0).toString(); QString pwd = sq.value(1).toString(); QString text ="dlchengg"; QTextStream output(sockets.at(i)); output<<text; } } else { QSqlError info = sq.lastError(); // 提取错误文本 QString text = info.text(); text.prepend("登录失败:"); QMessageBox::warning(this,"警告",text); } } void Dialog::selectName(QString name1,int i) { QString name=name1; QString sql = "SELECT * FROM book WHERE name LIKE ?"; QSqlQuery sq; sq.prepare(sql); sq.addBindValue(name); if(sq.exec()) { while(sq.next())// 循环取出 { // 取出一条数据库中的字段 QString time = sq.value(0).toString(); QString name = sq.value(1).toString(); QString msg = sq.value(2).toString(); QString msa="历史"; // 拼接并显示 QString text = msa.append(":")+time.append(":")+ name.append(":") + msg; QTextStream output(sockets.at(i)); output<< text<<endl; } } } void Dialog::selectNei(QString msg, int i) { QString sql = "SELECT * FROM book WHERE msg LIKE ?"; QSqlQuery sq; sq.prepare(sql); sq.addBindValue(msg.prepend("%").append("%")); if(sq.exec()) { while(sq.next())// 循环取出 { // 取出一条数据库中的字段 QString time = sq.value(0).toString(); QString name = sq.value(1).toString(); QString msg = sq.value(2).toString(); QString msa="历史"; // 拼接并显示 QString text = msa.append(":")+time.append(":")+ name.append(":") + msg; QTextStream output(sockets.at(i)); output<< text<<endl; } } } void Dialog::newConnSlot() { // 获得服务器端的连接类对象 socket = server->nextPendingConnection(); QTextStream output(socket); // 如果满员则踢出 if(sockets.size() == 20) { qDebug() << "聊天室满员"; output << QString("聊天室已达人数上限,连接失败!"); socket->close(); return; } sockets.append(socket); // 绿蛋收到消息的信号槽 connect(socket,SIGNAL(readyRead()), this,SLOT(readyReadSlot())); // 绿蛋掉线的信号槽 connect(socket,SIGNAL(disconnected()), this,SLOT(disconnetedSlot())); // 给客户端打个招呼 output << QString("服务器:你好啊!"); // 获得对面的IP地址和端口号 QString ip = socket->peerAddress().toString(); quint16 port = socket->peerPort(); QString portText = QString::number(port); QString text = "新连接来了!"; text.append(ip).append(":").append(portText); printMsg(text); } void Dialog::disconnetedSlot() { // 拿到发射者 socket = (QTcpSocket*)sender(); for(int i = 0;i<sockets.size();i++) { if(socket == sockets.at(i)) { qDebug() << "第" << i << "个客户端掉线了"; // 获得对面的IP地址和端口号 QString ip = sockets.at(i)->peerAddress().toString(); quint16 port = sockets.at(i)->peerPort(); QString portText = QString::number(port); QString text = "连接已断开!"; text.append(ip).append(":").append(portText); printMsg(text); sockets.removeAt(i); } } } //接收数据 void Dialog::readyReadSlot() { for(int i=0;i<sockets.size();i++) { if(sockets.at(i)->isReadable() && sockets.at(i)->bytesAvailable()>0) { qDebug() << "第" << i << "个客户端发的消息"; QTextStream input(sockets.at(i)); // 一口气都读了 QString text = input.readAll(); //写入数据库 QStringList list = text.split(":"); qDebug()<<"分割后数量"<<list.size(); if(list.size()==3) { QString time = list[0]; QString name = list[1]; QString msg = list[2]; if(list[2]=="历史记录") { selectAll( i); } else if(list[2]=="按照昵称") { selectName(name,i); } else if(list[0]=="按照内容") { selectNei(msg,i); } else { createTable(); QString sql = "INSERT INTO book VALUES(?,?,?);"; QSqlQuery sq; sq.prepare(sql); sq.addBindValue(time); sq.addBindValue(name); sq.addBindValue(msg); if(sq.exec()) { qDebug()<<"数据插入成功"; // QMessageBox::information(this,"通知","数据插入成功"); } else { // 获得错误信息封装类 QSqlError info = sq.lastError(); // 提取错误文本 QString text = info.text(); // 展示错误 text.prepend("数据插入失败:"); QMessageBox::warning(this,"警告",text); } printMsg(text); for(int m=0;m<sockets.size();m++) { if(m==i) continue; QTextStream output(sockets.at(m)); output << text; } } } else if(list.size()==2) { createTable2(); QString name = list[0]; QString pwd = list[1]; QString sql = "INSERT INTO class VALUES(?,?);"; QSqlQuery sq; sq.prepare(sql); sq.addBindValue(name); sq.addBindValue(pwd); if(sq.exec()) { qDebug()<<"注册成功"; // QMessageBox::information(this,"通知","数据插入成功"); } else { // 获得错误信息封装类 QSqlError info = sq.lastError(); // 提取错误文本 QString text = info.text(); // 展示错误 text.prepend("注册失败:"); QMessageBox::warning(this,"警告",text); } printMsg(text); for(int m=0;m<sockets.size();m++) { if(m==i) continue; QTextStream output(sockets.at(m)); output << text; } } else if(list.size()==4) { QString name = list[0]; QString pwd = list[1]; qDebug() << name<<pwd; QString sql = "SELECT * FROM class WHERE name=? AND pwd=?"; QSqlQuery sq; sq.prepare(sql); sq.addBindValue(name); sq.addBindValue(pwd); qDebug() << "yes"; if(sq.exec()) { // 取出一条数据库中的字段 while(sq.next()) { QString name = sq.value(0).toString(); QString pwd = sq.value(1).toString(); qDebug() <<name<<pwd; qDebug() << "yes"; QString text ="dlchengg"; QTextStream output(sockets.at(i)); output<<text; } } else { QSqlError info = sq.lastError(); // 提取错误文本 QString text = info.text(); text.prepend("登录失败:"); QMessageBox::warning(this,"警告",text); } } } } }