1.服务器:
1).功能:
用于创建一个客户端,通过文本编辑器来获得端口号,根据获得的端口号创建服务器,等待客户端连接
创建成功会提示服务器创建成功
在收到客户端发送的信息时,把这条信息发送给其他所有客户端,实现群聊功能
2).代码:
- -------------------------------------------------------------------
- .pro
- -------------------------------------------------------------------
- QT += core gui network
-
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++11
-
- # The following define makes your compiler emit warnings if you use
- # any Qt feature that has been marked deprecated (the exact warnings
- # depend on your compiler). Please consult the documentation of the
- # deprecated API in order to know how to port your code away from it.
- DEFINES += QT_DEPRECATED_WARNINGS
-
- # You can also make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- # You can also select to disable deprecated APIs only up to a certain version of Qt.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- main.cpp \
- widget.cpp
-
- HEADERS += \
- widget.h
-
- FORMS += \
- widget.ui
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
- -------------------------------------------------------------------
- widget.h
- -------------------------------------------------------------------
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Widget; }
- QT_END_NAMESPACE
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
- public slots:
- void connectbtn_slot();
- void connected_slot();
- void readyread_slot();
-
- private:
- Ui::Widget *ui;
-
- //定义服务器
- QTcpServer *server;
-
- //定义一个链表存放连接的客户端数据
- QList
client; -
- };
- #endif // WIDGET_H
- -------------------------------------------------------------------
- main.cpp
- -------------------------------------------------------------------
- #include "widget.h"
-
- #include
-
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- Widget w;
- w.show();
- return a.exec();
- }
- -------------------------------------------------------------------
- widget.cpp
- -------------------------------------------------------------------
- #include "widget.h"
- #include "ui_widget.h"
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
- //实例化服务器
- server = new QTcpServer(this);
-
-
- //连接按钮与对应槽函数
- connect(ui->connectbtn,&QPushButton::clicked,this,&Widget::connectbtn_slot);
-
- }
-
- Widget::~Widget()
- {
- delete ui;
- }
-
- //按下按钮后启动服务器
- void Widget::connectbtn_slot()
- {
- //读取端口号
- quint16 port = ui->portedit->text().toInt();
- //设置为监听状态
- if(!server->listen(QHostAddress::Any,port))
- {
- QMessageBox::critical(this,"失败","服务器启动失败");
- return ;
- }
- QMessageBox::information(this,"成功","服务器启动成功");
-
- //连接客户端信号与槽函数
- connect(server,&QTcpServer::newConnection,this,&Widget::connected_slot);
- }
-
- //客户端连接槽函数
- void Widget::connected_slot()
- {
- //获取客户端套接字
- QTcpSocket *cli = server->nextPendingConnection();
-
- //将得到的套接字写入链表
- client.push_back(cli);
- //把新套接字与接收信号连接
- connect(cli,&QTcpSocket::readyRead,this,&Widget::readyread_slot);
-
- }
-
- //有信息写入准备读取
- void Widget::readyread_slot()
- {
- //删除已经断开的客户端
- for(int i = 0;i < client.size();i++)
- {
- if(client.at(i)->state() == 0)
- {
- client.removeAt(i);
- }
- }
-
- //遍历发送数据的客户端
- for(int i = 0;i < client.size();i++)
- {
- if(client.at(i)->bytesAvailable() != 0)
- {
- //读取客户端数据
- QByteArray msg = client.at(i)->readAll();
- //将数据写到ui界面中
- ui->listWidget->addItem(QString::fromLocal8Bit(msg));
- //将数据发送给所有客户端
- for(int j = 0;j < client.size();j++)
- {
- client.at(j)->write(msg);
- }
- }
- }
-
- }
2.客户端:
登陆界面 :
1).功能:
输入账号密码,如果点击注册按钮,会将输入的账号密码存入数据库中
且对输入的账号密码进行判断(没输入账号会提示请输入账号,没输入密码会提示请输入密码),输入的账号不能重复,但是密码可以重复;
如果点击登录按钮,会读取数据库中注册的账号密码,与输入的账号密码进行对比,
如果一致则提示登录成功并跳转到聊天室界面,如果在数据库中找不到账号则提示账号不存在,如果存在账号但是密码不正确,则输出密码错误
2).代码:
- -------------------------------------------------------------------
- .pro
- -------------------------------------------------------------------
- QT += core gui network sql
-
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++11
-
- # The following define makes your compiler emit warnings if you use
- # any Qt feature that has been marked deprecated (the exact warnings
- # depend on your compiler). Please consult the documentation of the
- # deprecated API in order to know how to port your code away from it.
- DEFINES += QT_DEPRECATED_WARNINGS
-
- # You can also make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- # You can also select to disable deprecated APIs only up to a certain version of Qt.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- chat.cpp \
- main.cpp \
- widget.cpp
-
- HEADERS += \
- chat.h \
- widget.h
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
-
- RESOURCES += \
- Icon.qrc
-
- FORMS += \
- chat.ui
- -------------------------------------------------------------------
- widget.h
- -------------------------------------------------------------------
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include
-
- #include
- #include
- #include
- #include
-
- #include
- #include
-
- #include
- #include
-
-
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
- signals:
- void loginsuccess_signal(QString account);
-
- public slots:
- void loginbtn_slot();
- void signinbtn_slot();
-
- private:
- //组件
- QPushButton *login_btn;
- QPushButton *signin_btn;
- QLineEdit *account_edit;
- QLineEdit *pwd_edit;
- QLabel *main_lab;
- QLabel *account_lab;
- QLabel *pwd_lab;
-
- //数据库初始化
- QSqlDatabase db;
-
- };
- #endif // WIDGET_H
- -------------------------------------------------------------------
- main.cpp
- -------------------------------------------------------------------
- #include "widget.h"
- #include "chat.h"
-
- #include
-
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- Widget w;
- chat c;
- w.show();
-
- QObject::connect(&w,&Widget::loginsuccess_signal,&c,&chat::openchatroom_slot);
-
- return a.exec();
- }
- -------------------------------------------------------------------
- widget.cpp
- -------------------------------------------------------------------
- #include "widget.h"
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- {
- //---------------------------------窗口设置---------------------------------
- //设置窗口为固定大小
- this->setFixedSize(540,410);
- //设置窗口icon
- this->setWindowIcon(QIcon(":/icon/wodepeizhenshi.png"));
- //设置窗口名
- this->setWindowTitle("鹏哥快聊");
-
- //---------------------------------标签设置---------------------------------
- //=====创建界面标签=====
- main_lab = new QLabel(this);
- //修改标签大小
- main_lab->resize(540,200);
- //在标签中插入图片
- main_lab->setPixmap(QPixmap(":/icon/logo.png"));
- //设置为自适应
- main_lab->setScaledContents(1);
-
- //=====创建账号标签=====
- account_lab = new QLabel(this);
- //修改标签大小
- account_lab->resize(50,40);
- //在标签中插入图片
- account_lab->setPixmap(QPixmap(":/icon/userName.jpg"));
- //移动到合适位置
- account_lab->move(90,220);
- //设置为自适应
- account_lab->setScaledContents(1);
-
- //=====创建密码标签=====
- pwd_lab = new QLabel(this);
- //修改标签大小
- pwd_lab->resize(account_lab->size());
- //在标签中插入图片
- pwd_lab->setPixmap(QPixmap(":/icon/passwd.jpg"));
- //移动到合适位置
- pwd_lab->move(account_lab->x(),account_lab->y()+80);
- //设置为自适应
- pwd_lab->setScaledContents(1);
-
- //---------------------------------按钮设置---------------------------------
- //=====创建登录按钮=====
- login_btn = new QPushButton(this);
- //设置按钮大小
- login_btn->resize(100,40);
- //在按钮上插入图片
- login_btn->setIcon(QIcon(":/icon/login.png"));
- //在按钮上输入文本
- login_btn->setText("登录");
- //移动到合适位置
- login_btn->move(270,360);
- connect(login_btn,&QPushButton::clicked,this,&Widget::loginbtn_slot);
-
- //=====创建注册按钮=====
- signin_btn = new QPushButton(this);
- //设置按钮大小
- signin_btn->resize(100,40);
- //在按钮上插入图片
- signin_btn->setIcon(QIcon(":/icon/cancel.png"));
- //在按钮上输入文本
- signin_btn->setText("注册");
- //移动到合适位置
- signin_btn->move(login_btn->x()+120,login_btn->y());
- connect(signin_btn,&QPushButton::clicked,this,&Widget::signinbtn_slot);
-
- //---------------------------------输入设置---------------------------------
- //=====创建账号输入=====
- account_edit = new QLineEdit(this);
- //设置占位文本
- account_edit->setPlaceholderText("QQ号码/手机/邮箱");
- //设置大小
- account_edit->resize(200,40);
- //移动到适合位置
- account_edit->move(account_lab->x()+100,account_lab->y());
-
- //=====创建密码输入=====
- pwd_edit = new QLineEdit(this);
- //设置占位文本
- pwd_edit->setPlaceholderText("密码");
- //设置大小
- pwd_edit->resize(account_edit->size());
- //移动到合适位置
- pwd_edit->move(pwd_lab->x()+100,pwd_lab->y());
- //设置回文显示模式
- pwd_edit->setEchoMode(QLineEdit::Password);
-
- //--------------------------------数据库设置--------------------------------
- //判断数据库是否存在
- if(!db.contains("user.db"))
- {
- //不存在
- //创建一个数据库
- db = QSqlDatabase::addDatabase("QSQLITE");
- //命名为user.db
- db.setDatabaseName("user.db");
- }
- //存在
- //打开数据库
- if(!db.open())
- {
- //打开失败
- QMessageBox::critical(this,"error","数据库打开失败");
- return;
- }
- //打开成功
- //创建一个表
- //准备sql语句
- QString sql = "create table if not exists usertab("
- "account char primary key,"
- "passwd char)";
-
- //创建一个数据库指令执行者
- QSqlQuery commend;
- //执行sql语句
- if(!commend.exec(sql))
- {
- //创建表失败
- QMessageBox::critical(this,"error","表格创建失败");
- return;
- }
-
-
- }
-
- Widget::~Widget()
- {
- }
-
- //登录按钮槽函数
- void Widget::loginbtn_slot()
- {
- //获取账号和密码
- QString account = account_edit->text();
- QString passwd = pwd_edit->text();
- //从数据库中读取账号和密码
- QString sql = "select * from usertab";
- //创建执行者并执行sql语句
- QSqlQuery commend;
- if(!commend.exec(sql))
- {
- //查找失败
- QMessageBox::critical(this,"error","获取注册表失败");
- return;
- }
- //查找成功,循环比较数据库信息与输入的信息
- while (commend.next())
- {
- if(commend.value(0).toString() == account)
- {
- //账号正确
- if(commend.value(1).toString() == passwd)
- {
- QMessageBox::information(this,"success","登录成功");
- emit loginsuccess_signal(account);
- this->close();
- return;
- }
- //密码错误
- QMessageBox::critical(this,"failed","登录失败,密码错误");
- pwd_edit->clear();
- return;
- }
- }
- //账号错误
- QMessageBox::critical(this,"failed","登录失败,账号不存在");
- pwd_edit->clear();
- }
-
- //注册按钮槽函数
- void Widget::signinbtn_slot()
- {
- //判断是否填写完整信息
- if(account_edit->text() == "")
- {
- QMessageBox::critical(this,"error","请输入账号");
- return;
- }
- if(pwd_edit->text() == "")
- {
- QMessageBox::critical(this,"error","请输入密码");
- return;
- }
- //获取界面上的账号和密码
- QString account = account_edit->text();
- QString passwd = pwd_edit->text();
- //将注册的账号密码写入数据库中
- //准备sql语句
- QString sql = QString("insert into usertab values(\"%1\",\"%2\")")
- .arg(account).arg(passwd);
- //创建执行者并执行sql语句
- QSqlQuery commend;
- if(!commend.exec(sql))
- {
- //注册失败,账号重复
- QMessageBox::critical(this,"error","重复注册");
- return;
- }
- //注册成功
- QMessageBox::information(this,"success","注册成功");
- }
聊天室界面:
1).功能:
进入时,显示登录时的账号,且发送按钮、断开按钮和发送的文本编辑器不可用
通过主机的IP和端口号进行连接至主机后,给服务器发送xxx : 进入聊天室,发送按钮、断开按钮和发送的文本编辑器重新可用,使IP和端口号的文本编辑器以及连接聊天室按钮不可用
在发送的文本编辑器中写入信息并按下发送按钮后,会整合发送信息然后发送信息给服务器,发送后清空文本内容,
点击断开聊天室按钮,重新使发送按钮、断开按钮和发送的文本编辑器不可用,使IP和端口号的文本编辑器以及连接聊天室按钮可用
并会给服务器发送一条xxx : 离开聊天室的信息
2).代码:
- -------------------------------------------------------------------
- chat.h
- -------------------------------------------------------------------
- #ifndef CHAT_H
- #define CHAT_H
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- namespace Ui {
- class chat;
- }
-
- class chat : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit chat(QWidget *parent = nullptr);
- ~chat();
-
- public slots:
- void openchatroom_slot(QString account);
- void connectbtn_slot();
- void connected_slot();
- void readyread_slot();
- void sndbtn_slot();
- void disconbtn_slot();
- void disconnect_slot();
-
- private:
- Ui::chat *ui;
-
- //定义一个客户端套接字
- QTcpSocket *client;
-
- //定义一个用户名
- QString username;
-
- };
-
- #endif // CHAT_H
- -------------------------------------------------------------------
- chat.cpp
- -------------------------------------------------------------------
- #include "chat.h"
- #include "ui_chat.h"
-
- chat::chat(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::chat)
- {
- //将用户名居中显示
- //ui->usernamelab_2->setAlignment(Qt::AlignCenter);
-
- ui->setupUi(this);
- //为客户端套接字实例化空间
- client = new QTcpSocket(this);
- //连接按钮与对应槽函数连接
- connect(ui->connectbtn,&QPushButton::clicked,this,&chat::connectbtn_slot);
- //已连接信号与对应槽函数连接
- connect(client,&QTcpSocket::connected,this,&chat::connected_slot);
- //服务器发送信息信号与对应槽函数连接
- connect(client,&QTcpSocket::readyRead,this,&chat::readyread_slot);
- //发送按钮与对应槽函数连接
- connect(ui->sndbtn,&QPushButton::clicked,this,&chat::sndbtn_slot);
- //断开按钮与对应槽函数
- connect(ui->disconbtn,&QPushButton::clicked,this,&chat::disconbtn_slot);
- //断开连接信号与对应槽函数
- connect(client,&QTcpSocket::disconnected,this,&chat::disconnect_slot);
- //设置按钮与编辑框可用
- ui->disconbtn->setEnabled(0);
- ui->sndbtn->setEnabled(0);
- ui->msgedit->setEnabled(0);
- }
-
- chat::~chat()
- {
- delete ui;
- }
-
- void chat::openchatroom_slot(QString account)
- {
- username = account;
- qDebug() << account;
- qDebug() << username;
- ui->usernamelab_2->setText(username);
- this->show();
- }
-
- //连接按钮槽函数
- void chat::connectbtn_slot()
- {
- //从ui界面读取IP与port
- QString IP = ui->IPedit->text();
- quint16 port = ui->portedit->text().toUInt();
- //连接服务器
- client->connectToHost(IP,port);
- }
-
- //已连接槽函数
- void chat::connected_slot()
- {
- //连接完成提示信息
- QMessageBox::information(this,"成功","成功进入聊天室");
- //发送xx进入聊天室提示给服务器
- QString sndmsg = username + " : 进入聊天室";
- client->write(sndmsg.toLocal8Bit());
-
- //设置按钮与编辑框可用
- ui->IPedit->setEnabled(0);
- ui->portedit->setEnabled(0);
- ui->connectbtn->setEnabled(0);
- ui->sndbtn->setEnabled(1);
- ui->msgedit->setEnabled(1);
- ui->disconbtn->setEnabled(1);
-
- }
-
- //读取服务器发送信息
- void chat::readyread_slot()
- {
- //读取信息
- QByteArray msg = client->readAll();
- //将读取的信息发送到信息框内
- ui->listWidget->addItem(QString::fromLocal8Bit(msg));
- }
-
- //发送按钮对应槽函数
- void chat::sndbtn_slot()
- {
- //读取ui界面发送框内信息
- QString msg = ui->msgedit->text();
- msg = username + " : " + msg;
- //将数据发送给服务器
- client->write(msg.toLocal8Bit());
- ui->msgedit->clear();
- }
-
- //断开连接按钮对应槽函数
- void chat::disconbtn_slot()
- {
- //准备发送离开信息
- QString msg = username + " : 离开聊天室";
- client->write(msg.toLocal8Bit());
- //断开连接
- client->disconnectFromHost();
- }
-
- //断开连接信号槽函数
- void chat::disconnect_slot()
- {
- QMessageBox::information(this,"断开连接","成功退出聊天室");
- //设置按钮与编辑框可用
- ui->IPedit->setEnabled(1);
- ui->portedit->setEnabled(1);
- ui->connectbtn->setEnabled(1);
- ui->disconbtn->setEnabled(0);
- ui->sndbtn->setEnabled(0);
- ui->msgedit->setEnabled(0);
- }