用QT做一个聊天室,
制作一个服务器和客户端。可以进行注册、登录,
登陆成功后可以使用昵称进行发送、接收消息。
能根据昵称、聊天内容查询历史记录,也可以查询全部聊天记录。
。
//在pro文件里加入 QT += core gui network RC_FILE += icon_config.rc
//客户端dialog.h #ifndef DIALOG_H #define DIALOG_H #include #include // 网络连接类 #include // 文本流 #include #include #include 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<<":"<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() <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<<":"<textBrowser_2->clear(); QString user = ui->lineEditUser->text(); QString time = "hh"; // 创建文本流对象 QTextStream output(client); QString mm="按照昵称"; output<< time<<":"<textBrowser_2->clear(); QString user = "sjdhs"; QString time = "按照内容"; // 创建文本流对象 QString msg = ui->lineEditMsg->text(); if(msg == "") { QMessageBox::warning(this,"提示","请输入要发送的消息!"); return; } QTextStream output(client); output<< time<<":"<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 <lineEditUs->text(); if(user=="") { QMessageBox::warning(this,"提示","请输入昵称!"); return; } QString pwd = ui->lineEdit_2Pwd->text(); if(pwd == "") { QMessageBox::warning(this,"提示","请输入密码!"); return; } // 创建文本流对象 QTextStream output(client); // 连续输出发送 output <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 #include // 连接管理类 #include #include // 连接类 #include // 文本流 #include #include #include #include #include #include #include #include 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 sockets; QList 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<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;ipeerAddress().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;iisReadable() && sockets.at(i)->bytesAvailable()>0) { qDebug() << "第" << i << "个客户端发的消息"; QTextStream input(sockets.at(i)); // 一口气都读了 QString text = input.readAll(); //写入数据库 QStringList list = text.split(":"); qDebug()<<"分割后数量"<