#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
setWindowFlags(Qt::WindowStaysOnTopHint);
// 设置窗口标题
setWindowTitle("服务器");
//设置图标
QString icoPath=":/new/prefix1/images/ico1.ico";
QIcon ico(icoPath);
setWindowIcon(ico);
server = new QTcpServer(this); // 创建QTcpServer对象
// 绑定新来连接和对应槽函数
connect(server,SIGNAL(newConnection()),this,SLOT(newConnSlot()));
// 开启监听服务
bool result = server->listen(QHostAddress::Any,8886);
if(result)
printMsg("监听服务器开启成功......");
else
printMsg("监听服务器开启失败!");
connect2DB(); // 连接数据库并建表
}
Dialog::~Dialog()
{
// 如果服务器正在监听就关闭
if(server->isListening())
server->close();
db.close();
delete ui;
}
void Dialog::printMsg(QString msg)
{
QString text = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
ui->textBrowser->append(text);
ui->textBrowser->append(msg);
}
void Dialog::newConnSlot() // 新连接槽函数
{
// 获得服务器端的连接类对象
socket = server->nextPendingConnection(); // 获得新连接建立的QTcpSocket对象
QTextStream output(socket); // 服务器为本次连接的客户端创建输出流对象
// 如果满员则踢出
if(sockets.size() >= 10) // 最多10个人
{
qDebug() << "聊天室满了"+QString::number(sockets.size());
output << QString("聊天室已达人数上限,连接失败!");
socket->close();
return; // 结束本次连接
}
// 获得对面当前连接的客户端的IP和端口
QHostAddress ip = socket->peerAddress();
quint16 port = socket->peerPort();
QString ipStr = ip.toString();
QString portStr = QString::number(port);
QString text = "新连接来了!";
text.append(ipStr).append(":").append(portStr);
printMsg(text);
sockets.append(socket);
// 收到消息的信号槽
connect(socket,SIGNAL(readyRead()),this,SLOT(readyReadSlot()));
// 断连检测信号槽
connect(socket,SIGNAL(disconnected()),this,SLOT(disconnectedSlot()));
// 给客户端打个招呼
output << QString("服务器:你好啊!");
}
void Dialog::disconnectedSlot()
{
// 拿到发射者
socket = (QTcpSocket *)sender();
// 获得对面退出的客户的IP地址和端口号
QString ip = socket->peerAddress().toString();
quint16 port = socket->peerPort();
QString portText = QString::number(port);
QString text = "";
int toDelete = 0;
text.append(ip).append(":").append(portText);
for(int i = 0; i<sockets.size();i++)
{
if(socket == sockets.at(i))
{
qDebug() << "第" <<i<< "个客户掉线了";
printMsg("连接已断开!"+text);
toDelete = i;
}else
{
QTextStream output(sockets.at(i));
output << (text+"下线了...");
}
}
sockets.removeAt(toDelete); // 从列表中删除退出的用户
}
// 消息到来触发的槽函数,需对各类消息头进行判断以确定消息类型
void Dialog::readyReadSlot()
{
for(int i=0;i<sockets.size();i++) // sockets.size()是当前连接到服务器的客户端数量,不一定登陆了
{
if(sockets.at(i)->isReadable() && sockets.at(i)->bytesAvailable()>0)
{
qDebug() << "第" << i << "个客户端发的消息";
QTextStream input(sockets.at(i));
QString flagStr = input.readLine(256);
if(flagStr == "")
{
qDebug() <<"系统错误";
return;
}
QString str1 = input.readLine(256);
if(str1 == "")
{
qDebug() <<"用户名丢失!";
return;
}
QString str2 = input.readLine(256);
if(str2 == "")
{
qDebug() <<"密码丢失!";
return;
}
if(flagStr == "register") //如果是注册命令
registerFunc(str1, str2, sockets.at(i));
else if(flagStr == "login") //如果是登录命令
loginFunc(str1, str2, sockets.at(i));
else if(flagStr == "groupchat") // 如果是群聊消息
groupchatFunc(str1, str2, sockets.at(i)); // 注意这里str2是用户消息
else if(flagStr == "SelectAllRecord")
selectAllRecord(sockets.at(i));
else if(flagStr == "SelectMyRecord")
selectUserRecord(str1,sockets.at(i));
}
}
}
// 连接到数据库(没有则创建)
void Dialog::connect2DB()
{
// 创建数据库对象
db = QSqlDatabase::addDatabase("QSQLITE");
// 设置数据库文件名称
db.setDatabaseName("database.db");
// 尝试打开链接
if(db.open())
{
qDebug() << "数据库连接打开成功!";
createTable(); // 创建表
}else
{
QSqlError err = db.lastError(); // 获得错误信息对象
// 获得错误信息字符串
QString text = err.text();
QMessageBox::critical(this,"错误",text);
}
}
// 在数据库库中创建表(两个表)
void Dialog::createTable()
{
// SQL语句
QString sql1 = "CREATE TABLE Register(\
name TEXT PRIMARY KEY,\
password TEXT \
);\
";
QString sql2 = "CREATE TABLE GropChatRecords(\
name TEXT,\
message TEXT, \
time TEXT\
);\
";
// 创建数据库操作类对象
QSqlQuery sq;
// 执行SQL语句
if(sq.exec(sql1))
{
qDebug() << "建表Register成功!";
}else
{
QSqlError err = sq.lastError(); // 获得错误信息对象
// 获得错误信息字符串
QString text = err.text();
qDebug() << "建表Register失败!" << text;
}
if(sq.exec(sql2))
{
qDebug() << "建表GropChatRecords成功!";
}else
{
QSqlError err = sq.lastError(); // 获得错误信息对象
// 获得错误信息字符串
QString text = err.text();
qDebug() << "建表GropChatRecords失败!" << text;
}
}
// 注册函数
void Dialog::registerFunc(QString name, QString pwd, QTcpSocket *socket)
{
qDebug() <<"注册函数执行";
//创建文本流对象
QTextStream output(socket);
qDebug() <<"插入注册表";
QString sql="INSERT INTO Register VALUES(?,?)";
//预处理SQL语句
QSqlQuery sq;
sq.prepare(sql);
sq.addBindValue(name);
sq.addBindValue(pwd);
if(sq.exec())
{
//给客户端发送注册成功标志
QString text="register sucess";
output <<text;
qDebug()<<"新用户注册成功";
}
else
{
//给客户端发送注册失败标志
QString text="register fause";
output <<text;
text = sq.lastError().text();
text.prepend("新用户注册失败");
qDebug() <<text;
}
}
// 登录函数
void Dialog::loginFunc(QString name, QString pwd, QTcpSocket *socket)
{
qDebug() <<"登录函数执行";
//创建文本流对象
QTextStream output(socket);
//查询注册表看该用户是否注册过
qDebug() <<"查询注册表用户名";
QString sql = "SELECT * FROM Register WHERE name=?";
//预处理sql语句
QSqlQuery sq;
sq.prepare(sql);
sq.addBindValue(name);
QString flagStr = "";
QString text = "";
if(sq.exec())