Qt:基于QTcpSocket,QTcpServer编写的多人网络聊天室(TCPIP协议) —— 服务器源码

mac2022-06-30  26

编译环境:Ubuntu18.04,Qt5.11.2

QTcpSockServer.pro

TEMPLATE = app CONFIG += console c++11 CONFIG += console precompile_header CONFIG -= app_bundle CONFIG += qt QT += core gui network sql greaterThan(QT_MAJOR_VERSION, 4): QT += widgets HEADERS += \ CommonInc.h \ Database.h \ Structure.h \ TcpServer.h \ ServerSocket.h SOURCES += \ TcpServer.cpp \ Database.cpp \ main.cpp \ ServerSocket.cpp

main.cpp

#include <QCoreApplication> #include "CommonInc.h" #include "TcpServer.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 启动服务核心 TcpServer *server = new TcpServer(); if (!server->listen(QHostAddress::Any, Constant::LISTEN_PORT)) { QString strErr(QObject::tr("critical: Satrting server listen fail, error string:: ")); strErr += server->errorString(); qDebug("%s", strErr.toStdString().c_str()); exit(EXIT_FAILURE); } int ret = a.exec(); delete server; return ret; }

CommonInc.h

/********************************************* File Name: CommonInc.h Description: 封装公用头文件 ********************************************/ #ifndef COMMONINC_H #define COMMONINC_H #include <QObject> #include <QTcpServer> #include <QTcpSocket> #include <QMap> #include <QTextCodec> #include <QString> #include <QFont> #include <QColor> #include <QDateTime> #include <QDataStream> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlError> #include <QDebug> #include <QVector> #include <QVariant> #define TEST_SWITCH //测试开关 #endif // COMMONINC_H

structure.h

/********************************************* File Name: Structure.h Description: 封装结构体和常量 ********************************************/ #ifndef STRUCTURE_H #define STRUCTURE_H #include "CommonInc.h" class ServerSocket; //如果没有合适的翻译字符串,则返回QString::fromUtf8(sourceText) static const QString GROUP_NAME_DEFAULT = QString(QObject::tr("New Friend")); namespace Constant //常量 { const unsigned int LOGIN_TIMEOUT = 15; //(seconds)登录超时时间 const unsigned int LISTEN_PORT = 1234; //TCP监听端口 const QString DB_CLI_DRIVER = "QMYSQL"; //客户端数据库驱动名称 const QString DB_CLI_USERNAME = "root"; //客户端数据库用户名 const QString DB_CLI_PWD = ""; //客户端数据库密码 const QString DB_CLI_HOSTNAME = "localhost"; //客户端数据库主机名称(IP) const QString DB_CLI_DATABASE = "clientDB"; //客户端数据库名称 const QString DB_SER_DRIVER = "QMYSQL"; //服务读数据库驱动名称 const QString DB_SER_USERNAME = "root"; //服务端数据库用户名 const QString DB_SER_PWD = ""; //服务端数据库密码 const QString DB_SER_HOSTNAME = "localhost"; //服务端数据库主机名称(IP) const QString DB_SER_DATABASE = "serverDB"; //服务端数据库名称 } //服务器节点 struct ServerNode{ QString serIPaddress; //服务器地址 int serPort; //服务器端口 ServerNode(){serPort = 0;} }; // 登录状态 enum LoginStatus { LS_ONLINE = 0, // 在线 LS_INVISIBLE = 1, // 隐身 LS_BUSY = 2, // 忙碌 LS_LEAVE = 3, // 离开 LS_NOTDISTURB = 4, // 请勿打扰 LS_OFFLINE = 5 }; //群成员身份(未实现,暂保留) enum FlockStatus { FS_FLOCK_HOST = 0, // 群主 FS_FLOCK_ADMAIN = 1, // 群管理员 FS_FLOCK_MEMBER = 2 // 群成员 }; //讨论组成员身份(未实现,暂保留) enum DiscussionStatus { DS_DISCUSSION_HOST = 0, // 组长 DS_DISCUSSION_MEMBER = 1 // 组员 }; //email读/未读标记位(未实现,暂保留) enum EmailStatus { ES_MAIL_UNREAD = 0, ES_MAIL_READ = 1 }; // 信息(命令)类型 enum MessageType { /*********************** CToS ************************/ MT_CHECK_CONNECTION, // 检查能否与服务器连接 MT_LOGIN, // 登录 MT_REGISTER, // 注册 MT_GET_QUESTION_ANSWER, // 获取密保问题及答案 MT_GET_QUESTION_ANSWER_SUCCESS, MT_GET_QUESTION_ANSWER_FAIL, MT_CHECK_MESSAGE, // 检查有无给自己的信息(登录时检查) MT_GET_ALL_FRIENDS, // 获取所有好友信息 MT_TALK, // 发送对话 MT_ADD_FRIEND, // 添加好友 MT_GET_FRIEND_INFORMATION, // 获取好友信息 MT_DELETE_FRIEND, // 删除好友 MT_GET_MYSELF_INFORMATION, // 获取自己信息 MT_CHANGE_INFORMATION, // 改变自己的信息 MT_CHANGE_REMARK, // 改变(好友)备注 MT_CHANGE_PASSWORD, // 修改密码 MT_CHANGE_STATUE, // 改变自身状态 // 还有分组好友管理 MT_QUIT, // 退出 /*********************** SToC ************************/ MT_LOGIN_SUCCESS , // 登录成功 MT_LOGIN_FAIL, // 登录失败 MT_HAVE_LOGINED, // 已经登录 MT_REGISTER_SUCCESS, // 注册成功 MT_REGISTER_FAIL, // 注册失败 MT_REMOVE_BOX, // 删除分组 MT_REMOVE_BOX_SUCCESS, MT_REMOVE_BOX_FAIL, MT_RENAME_BOX, // 重命名分组 MT_RENAME_BOX_SUCCESS, MT_RENAME_BOX_FAIL, MT_CREATE_BOX, // 创建分组 MT_CREATE_BOX_SUCEESS, MT_CREATE_BOX_FAIL, MT_MOVE_FRIEND_BOX, // 移动好友至其他分组 36 MT_MOVE_FRIEND_BOX_SUCCESS, MT_MOVE_FRIEND_BOX_FAIL, MT_GET_ALL_FRIENDS_SUCCESS, // 获取所有好友信息成功 MT_GET_ALL_FRIENDS_FAIL, // 获取所有好友信息失败 MT_NO_FRIEND, // 没有好友 MT_NO_MESSAGE, // 没有信息 MT_HAVE_MESSAGE, // 有信息 MT_HAVE_TALK_MESSAGE, // 有聊天信息 MT_FRIEND_REQUESTED, // 好友请求 MT_FRIEDN_NO_ACCOUNT, // 没有这个用户名 MT_ALREAD_FRIENDS, // 回应好友请求 MT_GET_FRIEND_FAIL, MT_GET_FRIEND_SUCCESS, // 获得好友资料成功 MT_DELETE_FRIEND_FAIL, MT_DELETE_FRIEND_SUCCESS, // 删除好友成功 MT_GET_MYSELF_FAIL, MT_GET_MYSELF_SUCCESS, // 获得自己详细资料成功 MT_CHANGE_INFORMATION_FAIL, MT_CHANGE_INFORMATION_SUCCESS, // 改变自身资料成功 MT_CHANGE_REMARK_FAIL, // 修改备注失败 MT_CHANGE_REMARK_SUCCESS, // 修改备注成功 MT_OLD_PWD_IS_WRONG, // 旧密码是错的 MT_CHANGE_PWD_FAIL, // 修改密码失败 MT_CHANGE_PWD_SUCCESS, // 修改密码成功 /*********************** CToC ************************/ MT_REQUEST_FRIEND, // 请求添加好友 MT_AGREE_FRIEND, // 同意好友请求 MT_REFUSE_FRIEND, // 拒绝好友请求 MT_ADD_FRIEND_FAIL, // 添加好友失败 MT_ADD_FRIEND_SUCCESS, // 添加好友成功 MT_END_ADD_FRIEND, // 好友添加结束 MT_BE_DELETED, // 自己被好友删除了 MT_MESSAGE, // 普通信息 MT_TALK_MESSAGE, // 聊天信息 MT_GET_HISTORY_MESSAGE, // 历史消息 MT_GET_HISTORY_MESSAGE_SUCCESS, MT_GET_HISTORY_MESSAGE_FAIL }; // 存储聊天的字体和颜色 struct SaveFile { QFont m_Font; QColor m_Color; // 重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const SaveFile &sf) { out << sf.m_Font << sf.m_Color; return out; } friend QDataStream & operator>> (QDataStream &in, SaveFile &sf) { in >> sf.m_Font >> sf.m_Color; return in; } }; //邮件信息(未实现,暂保留) struct MailInformation { int m_MailID; QString m_SenderAddress; QString m_ReceiverAddress; QString m_Theme; QString m_Content; QDateTime m_dateTime; int m_Status; MailInformation() { m_Status = ES_MAIL_READ; } // 重载输入输出操作符 friend QDataStream &operator<<(QDataStream &out, const MailInformation &mail) { out << mail.m_MailID << mail.m_SenderAddress << mail.m_ReceiverAddress << mail.m_Theme << mail.m_Content << mail.m_dateTime << mail.m_Status; return out; } friend QDataStream &operator>>(QDataStream &in, MailInformation &mail) { in >> mail.m_MailID >> mail.m_SenderAddress >> mail.m_ReceiverAddress >> mail.m_Theme >> mail.m_Content >> mail.m_dateTime >> mail.m_Status; return in; } }; // 用户详细信息 struct UserInformation { int m_HeadPortrait; QString m_UserID; QString m_NickName; QString m_Password; QString m_Sex; QDate m_Birthday; QString m_Question; QString m_Answer; QString m_Name; QString m_Phone; QString m_Address; QDateTime m_RegDateTime; //QString m_Mark; int m_Status; UserInformation() { m_Status = LS_OFFLINE; m_HeadPortrait = 1; } // 重载输入输出操作符 friend QDataStream &operator<<(QDataStream &out, const UserInformation &user) { out << user.m_HeadPortrait << user.m_UserID << user.m_NickName << user.m_Password << user.m_Sex << user.m_Birthday << user.m_Question << user.m_Answer << user.m_Name << user.m_Phone << user.m_Address << user.m_RegDateTime << user.m_Status; return out; } friend QDataStream &operator>>(QDataStream &in, UserInformation &user) { in >> user.m_HeadPortrait >> user.m_UserID >> user.m_NickName >> user.m_Password >> user.m_Sex >> user.m_Birthday >> user.m_Question >> user.m_Answer >> user.m_Name >> user.m_Phone >> user.m_Address >> user.m_RegDateTime >> user.m_Status; return in; } }; // 好友信息 struct FriendInformation { int m_HeadPortrait; QString m_UserID; QString m_NickName; QString m_GroupName; QString m_RemarkName; int m_Status; FriendInformation() { m_Status = LS_OFFLINE; m_HeadPortrait = 1; m_GroupName = GROUP_NAME_DEFAULT; } //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const FriendInformation &fri) { out << fri.m_HeadPortrait << fri.m_UserID << fri.m_NickName << fri.m_GroupName << fri.m_RemarkName << fri.m_Status; return out; } friend QDataStream & operator>> (QDataStream &in, FriendInformation &fri) { in >> fri.m_HeadPortrait >> fri.m_UserID >> fri.m_NickName >> fri.m_GroupName >> fri.m_RemarkName >> fri.m_Status; return in; } }; // 储存在各种小窗口中填写的信息 struct TempStrings { QString m_One; QString m_Two; QString m_Three; //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const TempStrings &str) { out << str.m_One << str.m_Two << str.m_Three; return out; } friend QDataStream & operator>> (QDataStream &in, TempStrings &str) { in >> str.m_One >> str.m_Two >> str.m_Three; return in; } }; // 聊天框信息 struct ChatInformation { QString m_MyID; int m_HeadPortrait; QString m_FriendID; // 好友id QString m_FriendNickname; // 好友昵称 QString m_FriendRemark; // 好友备注 QString m_FriendMark; // 好友签名 QString m_FriendIP; // 好友ip地址 int m_FriendStatus; ChatInformation() { m_FriendStatus = LS_OFFLINE; m_HeadPortrait= 1; m_FriendMark = QString(QObject::tr("好友签名")); } }; // 对话信息 struct TalkMessage { int m_Type; // 消息类型 QString m_SenderID; // 发送者ID QString m_SenderIP; // 发送者IP QString m_ReceiverID; // 接收者ID QString m_ReceiverIP; // 接收者IP QString m_Text; // 消息内容 QDateTime m_dateTime; TalkMessage() { m_Type = 0; } //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const TalkMessage &mes) { out << mes.m_Type << mes.m_SenderID << mes.m_SenderIP << mes.m_ReceiverID << mes.m_ReceiverIP << mes.m_Text << mes.m_dateTime; return out; } friend QDataStream & operator>> (QDataStream &in, TalkMessage &mes) { in >> mes.m_Type >> mes.m_SenderID >> mes.m_SenderIP >> mes.m_ReceiverID >> mes.m_ReceiverIP >> mes.m_Text >> mes.m_dateTime; return in; } }; // 用户登录信息 struct LoginInformation { QString m_UserID; QString m_Password; int m_Status; LoginInformation() { m_Status = LS_OFFLINE; } //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const LoginInformation &li) { out << li.m_UserID << li.m_Password << li.m_Status; return out; } friend QDataStream & operator>> (QDataStream &in, LoginInformation &li) { in >> li.m_UserID >> li.m_Password >> li.m_Status; return in; } }; // 群成员信息(未实现,暂保留) struct FlockMember { QString m_FlockID; // 群ID QString m_UserID; // 用户ID int m_HeadPortrait; // 用户头像编号 QString m_Nickname; // 用户昵称 int m_LoginStatus; // 用户登录状态 QString m_Remark; // 用户群名片 int m_FlockStatus; // 用户身份 QDateTime m_dateTimejoin; // 加入时间 //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const FlockMember &flockMember) { out << flockMember.m_FlockID << flockMember.m_UserID << flockMember.m_HeadPortrait << flockMember.m_Nickname << flockMember.m_LoginStatus << flockMember.m_Remark << flockMember.m_FlockStatus << flockMember.m_dateTimejoin; return out; } friend QDataStream & operator>> (QDataStream &in, FlockMember &flockMember) { in >> flockMember.m_FlockID >> flockMember.m_UserID >> flockMember.m_HeadPortrait >> flockMember.m_Nickname >> flockMember.m_LoginStatus >> flockMember.m_Remark >> flockMember.m_FlockStatus >> flockMember.m_dateTimejoin; return in; } }; // 讨论组成员信息(未实现,暂保留) struct DiscussionMember { QString m_DiscussionID; // 讨论组ID QString m_UserID; // 用户ID int m_HeadPortrait; // 用户头像编号 QString m_NickName; // 用户昵称 int m_LoginStatus; // 用户登录状态 int m_DiscussionStatus; // 用户身份 QDateTime m_dateTimejoin; // 加入时间 //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const DiscussionMember &disMember) { out << disMember.m_DiscussionID << disMember.m_UserID << disMember.m_HeadPortrait << disMember.m_NickName << disMember.m_LoginStatus << disMember.m_DiscussionStatus << disMember.m_dateTimejoin; return out; } friend QDataStream & operator>> (QDataStream &in, DiscussionMember &disMember) { in >> disMember.m_DiscussionID >> disMember.m_UserID >> disMember.m_HeadPortrait >> disMember.m_NickName >> disMember.m_LoginStatus >> disMember.m_DiscussionStatus >> disMember.m_dateTimejoin; return in; } }; // 群信息(未实现,暂保留) struct FlockInformation { QString m_FlockID; QString m_CreatorID; QDate m_CreateDate; QString m_FlockName; QString m_Theme; //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const FlockInformation &flock) { out << flock.m_FlockID << flock.m_CreatorID << flock.m_CreateDate << flock.m_FlockName << flock.m_Theme; return out; } friend QDataStream & operator>> (QDataStream &in, FlockInformation &flock) { in >> flock.m_FlockID >> flock.m_CreatorID >> flock.m_CreateDate >> flock.m_FlockName >> flock.m_Theme; return in; } }; // 讨论组信息(未实现,暂保留) struct DiscussionInformation { QString m_DiscussionID; QString m_CreatorID; QDate m_CreateDate; QString m_DiscussionName; QString m_Theme; //重载输入输出操作符 friend QDataStream & operator<< (QDataStream &out, const DiscussionInformation &dis) { out << dis.m_DiscussionID << dis.m_CreatorID << dis.m_CreateDate << dis.m_DiscussionName << dis.m_Theme; return out; } friend QDataStream & operator>> (QDataStream &in, DiscussionInformation &dis) { in >> dis.m_DiscussionID >> dis.m_CreatorID >> dis.m_CreateDate >> dis.m_DiscussionName >> dis.m_Theme; return in; } }; // 存储临时信息的结构体,用于信号/糟 struct SaveTmpInformation { int m_RequestKind; int m_ReplyKind; ServerSocket *m_ServerSocket; QString m_MyID; QString m_PeerID; QDate m_Date; QString m_GroupName; QString m_GroupNameF; UserInformation m_UserInf; LoginInformation m_LoginInf; FriendInformation m_FriendInf; TalkMessage m_Message; int m_Status; TempStrings m_TempStr; QVector<TalkMessage> m_MessageVec; QVector<FriendInformation> m_FriendsVec; QVector<QString> m_IDVec; QString m_FlockID; FlockMember m_FlockMember; FlockInformation m_FlockInf; QVector<FlockInformation> m_FlocksVec; QVector<FlockMember> m_FlockMembersVec; QString m_DiscussionID; DiscussionMember m_DiscussionMember; DiscussionInformation m_DiscussionInf; QVector<DiscussionInformation> m_DiscussionsVec; QVector<DiscussionMember> m_DiscussionMembersVec; int m_MailID; MailInformation m_Mail; QVector<MailInformation> m_InMailsVec; QVector<MailInformation> m_OutMailsVec; QString m_Title; QString m_NewTitle; QString m_SocketID; QVector<TalkMessage> m_HistoryMessageVec; }; //头像尺寸 const int HEAD_BIG_SIZE = 40; const int HEAD_SMALL_SIZE = 35; const int HEAD_MINI_SIZE = 20; //聊天室 工具栏尺寸 const int CHAT_WIDGET_TOOL_SIZE = 20; const int CHAT_WIDGET_TOOL_SMALL_SIZE = 15; //字体大小 const int FONT_SIZE = 2; //邮件地址格式 static const QString MAIL_ADDRESS_FORMAT = "@hackt.com"; //本地/网络历史消息记录存放地址 static const QString LOCAL_HISTORY_MESSAGE_PATH = "resource/history/local/"; static const QString NETWORK_HISTORY_MESSAGE_PATH = "resource/history/network/"; #endif // STRUCTURE_H

Database.h

/********************************************* File Name: Database.h Description: 数据库操作类 ********************************************/ #ifndef DATABASE_H #define DATABASE_H #include "CommonInc.h" #include "Structure.h" class QSqlQuery; class QDateTime; class QSqlDatabase; class Database : public QObject { Q_OBJECT public: Database(QObject *parent = nullptr); ~Database(); //创建连接 bool createConnection(); //初始化数据库,并将所有用户的状态status设置为OFFLINE bool initDatabase(); //关闭数据库(库函数) void close(); //打开数据库(库函数) bool isOpen(); //修改、更新密码 int updatePassword(TempStrings &tmp); // 查询密保问题以及答案 int searchQuestionAndAnswer(const QString &id, TempStrings & tmp); // 查询用户 int searchUserInUserInformation(const LoginInformation &logInf, UserInformation &userInf); // 通过id查询好友信息 int searchFriendInformationByID(const QString &id, UserInformation &userInf); // 通过id查询自己信息 int searchMyselfInformationByID(const QString &id, UserInformation &userInf); // 修改用户信息 int updateMyselfInformation(const UserInformation &user); // 添加用户 int addUserInUserInformation(const UserInformation &userInf); // 获取一段时间注册数量 int countRegisteredInPeriod(const QDateTime &datePre, const QDateTime &dateLater); // 获取所有好友信息 int searchFriendsInformation(const QString &id, QVector<FriendInformation> &friendsVec); // 获取所有好友ID bool searchFriendsID(const QString &id, QVector<QString> &IDVec); // 更新好友状态 bool updateStatus(int status, const QString & id); // 更新好友备注 int updateRemark(const TempStrings & tmpStr); // 删除好友 int deleteFriend(const QString & myID, const QString & friendID, QString & groupName, QString & groupNameF); // 添加好友 bool addFriend(const TalkMessage & talMes); //插入DateCounterb表某日的数据项 bool insertValuesInDateCounter(const QDate &date); // 获取某日用户注册数量+1 int getUserTimes(const QDate &date); // 增加某日用户注册数量 bool increaseUserTimes(const QDate &date); // 移动好友至其他分组 int moveFriendToGroup(const QString & myID, const QString & friendID, const QString & title, const QString & newTitle); // 重命名分组 int renameGroup(const QString & id, const QString & title, const QString & newTitle); // 存储历史记录 bool addHistoryMsg(const TalkMessage &talMes); // 存储离线记录 bool addOfflineMsg(const TalkMessage &talMes); // 获取用户的某日与某位好友的聊天记录 int searchHistoryMsgOfFriendInDate(const QString & myID, const QString &friendID, const QDate & date, QVector<TalkMessage> & mesVec); private: //检查SQL语句的正确性 void errorSQLOrder(QSqlQuery query, QString mark); //创建数据库表格 void createTable(); QSqlDatabase *m_SqlDatabase; }; #endif // DATABASE_H

Database.cpp

/********************************************* File Name: Database.cpp Description: 操作数据库 ********************************************/ #include <QSqlDatabase> #include <QSqlQuery> #include <QVariant> #include <qdebug.h> #include <QSqlError> #include <QTextDocument> #include "Database.h" //更新用户在线状态 static const QString UPDATE_STATUS_IN_USERINFORMATION_SQL = "update UserInformation set status = 5"; //更新用户密码 static const QString UPDATE_PASSWORD_IN_USERINFORMATION_SQL = "update UserInformation set password = ?" "where user = ? and password = ?"; // 查询用户密码和密保问题 static const QString SEARCH_QUESTION_ANSWER_IN_USERINFORMATION_SQL = "select password, question, answer from UserInformation where userID = ?;"; // 查询用户信息 static const QString SEARCH_USER_IN_USERINFORMATION_SQL = "select * from UserInformation where (userID = ? and password = ?)"; // 查询用户信息 static const QString SEARCH_USER_IN_USERINFORMATION_ID_SQL = "select * from UserInformation where userID = ?"; // 更新用户信息 static const QString UPDATE_USERINFORMATION_SQL = "update UserInformation set " "head = ?, nickname = ?, sex = ?, birthday = ?, " "name = ?, phone = ?, address = ? where userID = ?;"; // 更新用户在线状态 static const QString UPDATE_STATUS_IN_USERINFORMATION_BY_ID_SQL= "update UserInformation set status = ? where userID = ?;"; // 更新用户的个性签名 static const QString UPDATE_REMARKNAME_IN_USERFRIENDS_SQL= "update UserFriends set remarkName = ? where userID = ? and friendID = ?;"; // 插入一条记录到UserInformation表中 static const QString ADD_USER_IN_USERINFORMATION_SQL = "insert into UserInformation values(?,?,?,?,?,?,?,?,?,?,?,?,?)"; // 查询某段时间内注册的用户数量 static const QString COUNT_REGISTERED_USERS_IN_USERINFORMATION_SQL = "select count(*) from UserInformation where regDate >= ? and regDate < ?"; // 在好友中搜索好友信息 static const QString SEARCH_FRIENDS_IN_USERFRIENDS_USERINFORMATION_SQL = "select UserFriends.groupName, UserFriends.friendID, " "UserInformation.nickName, UserFriends.remarkName," "UserInformation.status, UserInformation.head " "from UserFriends,UserInformation " "where UserFriends.userID = ? " "and UserInformation.userID = UserFriends.friendID;"; // 查询某个用户的所有好友 static const QString SEARCH_ID_IN_USERFRIENDS_SQL = "select friendID from UserFriends where userID = ?"; // 查询某个分组下的好友信息 static const QString SEARCH_GROUPNAME_IN_USERFRIENDS_SQL = "select groupName from UserFriends where userID = ? and friendID = ?"; // 从好友分组中移除某个好友 static const QString DELETE_FRIEND_IN_USERFRIENDS_SQL = "delete from UserFriends where " "(userID = ? and friendID = ?) or " "(userID = ? and friendID = ?)"; // 插入好友到用户的分组中 static const QString ADD_FRIEND_IN_USERFRIENDS_SQL = "insert into UserFriends(userID, friendID, groupName) values (?, ?, ?);"; // 统计DataCounter表中的记录数 static const QString COUNT_DATARECORD_IN_DATECOUNTER_SQL = "select count(*) from DateCounter where date = ?;"; // 插入一条记录到DataCounter表中 static const QString INSERT_VALUES_IN_DATECOUNTER_SQL = "insert into DateCounter values(?, 0, 0, 0);"; // 查询当天用户注册数量 static const QString SELECT_USERTIMES_IN_DATECOUNTER_SQL = "select userTimes from DateCounter where date = ?;"; // 更新当天用户注册量 static const QString INCREASE_USERTIMES_IN_DATECOUNTER_SQL = "update DateCounter set userTimes = userTimes + 1 where date = ?;"; /************************ group ***************************/ // 修改/移动好友所属分组 static const QString RENAME_GROUPNAME_IN_USERFREINS = "update UserFriends set groupName = ? where userID = ? and groupName = ?;"; // 修改/移动好友所属分组 static const QString MOVE_FRIEND_IN_USERFREINS = "update UserFriends set groupName = ? where userID = ? " "and friendID = ?;"; /************************ message ************************/ // 插入聊天记录到HistoryMessage表中 static const QString INSERT_MESSAGE_IN_HISTORYMESSAGE = "insert into HistoryMessage (senderID, receiverID, content, dateTime) " "values(?, ?, ?, ?); "; // 插入离线消息到OfflineMessage表中 static const QString INSERT_MESSAGE_IN_OFFLINEMESSAGE = "insert into OfflineMessage (kind, senderID, receiverID, content) " "values(?, ?, ?, ?);"; // 查询历史消息 static const QString SEARCH_FRIEND_DATE_MESSAGE_IN_HISTORYMESSAGE = "select senderID, receiverID, content, dateTime from HistoryMessage " "where ( (senderID = ? and receiverID = ?) " "or (senderID = ? and receiverID = ?) ) " "and dateTime >= ? and dateTime < ?;"; /********************create tables********************/ static const QString CREATE_TABLE_USERINFORMATION_SQL = ""; static const QString CREATE_TABLE_USERFRIENDS_SQL = ""; static const QString CREATE_TABLE_TMPMESSAGE_SQL = ""; //html转QString QString simplifyRichText(QString richText) { QTextDocument doc; doc.setHtml(richText); qDebug() << "say:"<< doc.toPlainText(); return doc.toPlainText(); } Database::Database(QObject *parent) : QObject(parent) { m_SqlDatabase = new QSqlDatabase; } Database::~Database() { if (m_SqlDatabase != nullptr) { if (m_SqlDatabase->isOpen()) m_SqlDatabase->close(); delete m_SqlDatabase; m_SqlDatabase = nullptr; } } bool Database::createConnection() //创建数据库连接 { if(m_SqlDatabase == nullptr) { m_SqlDatabase = new QSqlDatabase; } if(m_SqlDatabase->isOpen()) { return true; } //如果已经打开数据库 if(QSqlDatabase::contains("serverDB")) { *m_SqlDatabase = QSqlDatabase::database("serverDB"); }else { //如果没有打开,则添加 *m_SqlDatabase = QSqlDatabase::addDatabase(Constant::DB_CLI_DRIVER,Constant::DB_SER_DATABASE); m_SqlDatabase->setDatabaseName(Constant::DB_CLI_DATABASE); } m_SqlDatabase->setUserName(Constant::DB_SER_USERNAME); m_SqlDatabase->setPassword(Constant::DB_SER_PWD); m_SqlDatabase->setHostName(Constant::DB_SER_HOSTNAME); if(!m_SqlDatabase->open()) { QSqlError sqlError = m_SqlDatabase->lastError(); QString errorString = sqlError.text(); return false; } return true; } bool Database::initDatabase() //初始化数据库,将所有用户状态status置为OFFLINE { if(!createConnection()) { return false; } QSqlQuery sqlQuery(*m_SqlDatabase); sqlQuery.exec(UPDATE_STATUS_IN_USERINFORMATION_SQL); errorSQLOrder(sqlQuery, "initDatabase"); if(!sqlQuery.isActive()) { m_SqlDatabase->close(); return false; } m_SqlDatabase->close(); return false; } void Database::close() //关闭数据库 { if(m_SqlDatabase != nullptr && m_SqlDatabase->isOpen()) { m_SqlDatabase->close(); } } bool Database::isOpen() //数据库是否打开 { return m_SqlDatabase->isOpen(); } int Database::updatePassword(TempStrings &tmp) { if(!createConnection()) { return MT_CHANGE_PWD_FAIL; } //sql事务 QSqlDatabase::database().transaction(); //如果驱动程序支持事务,则在数据库上开始事务 QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(UPDATE_PASSWORD_IN_USERINFORMATION_SQL); //如果要执行的SQL查询准备成功,返回true,否则返回false sqlquery.addBindValue(tmp.m_Three); //使用位置值绑定时,将值val添加到值列表中 sqlquery.addBindValue(tmp.m_One); sqlquery.addBindValue(tmp.m_Two); sqlquery.exec(); //执行先前准备的SQL查询,如果查询成功执行,返回true,否则返回false errorSQLOrder(sqlquery,"update pwd"); QSqlDatabase::database().commit(); //将修改提交并保存到数据库,完成这个事务 if(!sqlquery.isActive()) //isActive():如果查询处于活动状态(成功执行exec(),但尚未完成的Qsqlquery),则返回true { m_SqlDatabase->close(); return MT_CHANGE_PWD_FAIL; } qDebug() << "size:" << sqlquery.numRowsAffected(); //返回受结果SQL语句影响的行数,如果无法确定,则返回-1 if(sqlquery.numRowsAffected() <= 0) { m_SqlDatabase->close(); return MT_CHANGE_PWD_FAIL; } qDebug() << "size:" << sqlquery.numRowsAffected(); return MT_CHANGE_PWD_SUCCESS; } int Database::searchQuestionAndAnswer(const QString &id, TempStrings &tmp) //查询密保问题及答案 { if(!createConnection()) { return MT_GET_QUESTION_ANSWER_FAIL; } //Sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SEARCH_QUESTION_ANSWER_IN_USERINFORMATION_SQL); sqlquery.addBindValue(id); sqlquery.exec(); errorSQLOrder(sqlquery,"forget pwd"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return MT_GET_QUESTION_ANSWER_FAIL; } if(sqlquery.size() <= 0)//返回结果的大小(返回的行数);如果无法确定大小,或者数据库不支持有关查询大小的报告信息,则返回-1 { m_SqlDatabase->close(); return MT_GET_QUESTION_ANSWER_FAIL; } /*检索结果中的下一个记录(如果有),将查询放在检索到的记录上。 如果无法检索记录,则将结果放置在最后一条记录之后并返回false。如果成功检索到记录,则返回true*/ if(sqlquery.next()) { tmp.m_One = sqlquery.value(0).toString(); tmp.m_Two = sqlquery.value(1).toString(); tmp.m_Three = sqlquery.value(2).toString(); return MT_GET_QUESTION_ANSWER_SUCCESS; } return MT_GET_QUESTION_ANSWER_FAIL; } int Database::searchUserInUserInformation(const LoginInformation &logInf, UserInformation &userInf) //查询用户(登录信息) { if(!createConnection()) { return MT_LOGIN_FAIL; } //Sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SEARCH_USER_IN_USERINFORMATION_SQL); sqlquery.addBindValue(logInf.m_UserID); sqlquery.addBindValue(logInf.m_Password); sqlquery.exec(); errorSQLOrder(sqlquery,"login search"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return MT_LOGIN_FAIL; } if(sqlquery.size() <= 0) { m_SqlDatabase->close(); return MT_LOGIN_FAIL; } if(sqlquery.next()) { userInf.m_UserID = sqlquery.value(0).toString(); userInf.m_NickName = sqlquery.value(1).toString(); userInf.m_Sex = sqlquery.value(2).toString(); userInf.m_Birthday = sqlquery.value(3).toDate(); userInf.m_Address = sqlquery.value(4).toString(); userInf.m_HeadPortrait = sqlquery.value(5).toInt(); userInf.m_Phone = sqlquery.value(6).toString(); userInf.m_RegDateTime = sqlquery.value(7).toDateTime(); userInf.m_Name = sqlquery.value(8).toString(); userInf.m_Status = logInf.m_Status; qDebug() << "searchUserInUserInformation:" << userInf.m_Status; if(updateStatus(logInf.m_Status, logInf.m_UserID)) { return MT_LOGIN_SUCCESS; } } return MT_LOGIN_FAIL; } int Database::searchFriendInformationByID(const QString &id, UserInformation &userInf) //通过id查询好友信息 { if(!createConnection()) { return MT_GET_FRIEND_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.addBindValue(id); sqlquery.exec(); errorSQLOrder(sqlquery, "friend inf search"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return MT_GET_FRIEND_FAIL; } if(sqlquery.size() <= 0) { m_SqlDatabase->close(); return MT_GET_FRIEND_FAIL; } if(sqlquery.next()) { userInf.m_UserID = sqlquery.value(0).toString(); userInf.m_NickName = sqlquery.value(1).toString(); userInf.m_Sex = sqlquery.value(2).toString(); userInf.m_Birthday = sqlquery.value(3).toDate(); userInf.m_Address = sqlquery.value(4).toString(); userInf.m_HeadPortrait = sqlquery.value(5).toInt(); userInf.m_Phone = sqlquery.value(6).toString(); userInf.m_RegDateTime = sqlquery.value(7).toDateTime(); userInf.m_Name = sqlquery.value(8).toString(); userInf.m_Status = sqlquery.value(9).toInt(); } return MT_GET_FRIEND_SUCCESS; } int Database::searchMyselfInformationByID(const QString &id, UserInformation &userInf) //通过id查询自己的信息 { if(!createConnection()) { return MT_GET_MYSELF_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SEARCH_USER_IN_USERINFORMATION_ID_SQL); sqlquery.addBindValue(userInf.m_NickName); sqlquery.addBindValue(userInf.m_Sex); sqlquery.addBindValue(userInf.m_Birthday); sqlquery.addBindValue(userInf.m_Name); sqlquery.addBindValue(userInf.m_Phone); sqlquery.addBindValue(userInf.m_Address); sqlquery.addBindValue(userInf.m_UserID); sqlquery.addBindValue(id); sqlquery.exec(); errorSQLOrder(sqlquery, "myself inf search"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return MT_GET_MYSELF_FAIL; } if(sqlquery.size() <= 0) { m_SqlDatabase->close(); return MT_GET_MYSELF_FAIL; } if(sqlquery.next()) { userInf.m_UserID = sqlquery.value(0).toString(); userInf.m_NickName = sqlquery.value(1).toString(); userInf.m_Sex = sqlquery.value(2).toString(); userInf.m_Birthday = sqlquery.value(3).toDate(); userInf.m_Address = sqlquery.value(4).toString(); userInf.m_HeadPortrait = sqlquery.value(5).toInt(); userInf.m_Phone = sqlquery.value(6).toString(); userInf.m_RegDateTime = sqlquery.value(7).toDateTime(); userInf.m_Name = sqlquery.value(8).toString(); userInf.m_Status = sqlquery.value(9).toInt(); } return MT_GET_MYSELF_SUCCESS; } int Database::updateMyselfInformation(const UserInformation &userInf) //修改用户信息 { if(!createConnection()) { return MT_CHANGE_INFORMATION_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(UPDATE_USERINFORMATION_SQL); sqlquery.addBindValue(userInf.m_HeadPortrait); sqlquery.addBindValue(userInf.m_NickName); sqlquery.addBindValue(userInf.m_Sex); sqlquery.addBindValue(userInf.m_Birthday); sqlquery.addBindValue(userInf.m_Name); sqlquery.addBindValue(userInf.m_Phone); sqlquery.addBindValue(userInf.m_Address); sqlquery.addBindValue(userInf.m_UserID); sqlquery.exec(); errorSQLOrder(sqlquery, "change update userinf"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { //lastError():返回有关此查询发生的最后一个错误(如果有)的错误信息 qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_CHANGE_INFORMATION_FAIL; } return MT_CHANGE_INFORMATION_SUCCESS; } int Database::addUserInUserInformation(const UserInformation &userInf) //添加用户 { if(!createConnection()) { return MT_REGISTER_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(ADD_USER_IN_USERINFORMATION_SQL); sqlquery.addBindValue(userInf.m_UserID); sqlquery.addBindValue(userInf.m_HeadPortrait); sqlquery.addBindValue(userInf.m_NickName); sqlquery.addBindValue(userInf.m_Password); sqlquery.addBindValue(userInf.m_Sex); sqlquery.addBindValue(userInf.m_Birthday.toString("yyyy-MM-dd")); sqlquery.addBindValue(userInf.m_Question); sqlquery.addBindValue(userInf.m_Answer); sqlquery.addBindValue(userInf.m_Name); sqlquery.addBindValue(userInf.m_Phone); sqlquery.addBindValue(userInf.m_Address); sqlquery.addBindValue(userInf.m_RegDateTime);//.toString("yyyy-MM-dd hh:mm:ss")); sqlquery.addBindValue(5); sqlquery.exec(); errorSQLOrder(sqlquery, "register add"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL::" << sqlquery.lastError().text();//返回有关此查询发生的最后一个错误(如果有)的错误信息 m_SqlDatabase->close(); return MT_REGISTER_FAIL; } if(!increaseUserTimes(QDate::currentDate())) { return MT_REGISTER_FAIL; } return MT_REGISTER_SUCCESS; } int Database::countRegisteredInPeriod(const QDateTime &datePre, const QDateTime &dateLater) //获取一段时间内的用户注册数量 { int count = 0; qDebug() << "A period of date:" << datePre.toString("yyyy-MM-dd hh:mm:ss") << dateLater.toString("yyyy-MM-dd hh:mm:ss"); if(!createConnection()) { return 0; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(COUNT_REGISTERED_USERS_IN_USERINFORMATION_SQL); sqlquery.addBindValue(datePre); sqlquery.addBindValue(dateLater); sqlquery.exec(); errorSQLOrder(sqlquery, "register count"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return 0; } while(sqlquery.next()) { count = sqlquery.value(0).toInt() + 1; } return count; } int Database::searchFriendsInformation(const QString &id, QVector<FriendInformation> &friendsVec) //获取所有好友信息 { if(!createConnection()) { return MT_GET_ALL_FRIENDS_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SEARCH_FRIENDS_IN_USERFRIENDS_USERINFORMATION_SQL); sqlquery.addBindValue(id); sqlquery.exec(); errorSQLOrder(sqlquery, "get all friend search"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return MT_GET_ALL_FRIENDS_FAIL; } friendsVec.clear(); //从向量中删除所有元素 while(sqlquery.next()) { FriendInformation friInf; friInf.m_GroupName = sqlquery.value(0).toString(); friInf.m_UserID = sqlquery.value(1).toString(); friInf.m_NickName = sqlquery.value(2).toString(); friInf.m_RemarkName = sqlquery.value(3).toString(); friInf.m_Status = sqlquery.value(4).toInt(); friInf.m_HeadPortrait = sqlquery.value(5).toInt(); friendsVec.push_back(friInf); //提供此功能是为了实现STL兼容性,等效于append(value) } if(friendsVec.isEmpty()) { return MT_NO_FRIEND; } return MT_GET_ALL_FRIENDS_SUCCESS; } bool Database::searchFriendsID(const QString &id, QVector<QString> &friVec) //获取所有好友ID { friVec.clear(); if(!createConnection()) { return false; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SEARCH_ID_IN_USERFRIENDS_SQL); sqlquery.addBindValue(id); sqlquery.exec(); errorSQLOrder(sqlquery, "get all friend id search"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return false; } while(sqlquery.next()) { friVec.push_back(sqlquery.value(0).toString()); } return true; } void Database::errorSQLOrder(QSqlQuery sqlquery, QString flog) //检查SQL语句的正确性 { //如果SQL语句错误,就弹出警告信息 if(!sqlquery.isActive()) { QString str = sqlquery.lastError().text() + '\n' + flog; qDebug() << "Mysql query error:" << str; qDebug() << "sqlquery text:" << sqlquery.lastQuery(); //返回正在使用的当前查询的文本,如果没有当前查询文本,则返回一个空字符串 } else { qDebug() << Constant::DB_SER_DRIVER << "excute success:"; qDebug() << "sql text:" << sqlquery.lastQuery(); } } void Database::createTable() //创建数据库表格 { //预留接口函数 } bool Database::updateStatus(int status, const QString &id) //更新好友状态 { qDebug() << "status is:" << status; if(!createConnection()) { return false; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(UPDATE_STATUS_IN_USERINFORMATION_BY_ID_SQL); sqlquery.addBindValue(id); sqlquery.addBindValue(status); sqlquery.exec(); errorSQLOrder(sqlquery, "quit update status"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } return true; } int Database::updateRemark(const TempStrings & tmpStr)//更新好友备注 { if (!createConnection()) { return MT_CHANGE_REMARK_FAIL; } //sql 事务 QSqlDatabase::database().transaction(); QSqlQuery query(*m_SqlDatabase); query.prepare(UPDATE_REMARKNAME_IN_USERFRIENDS_SQL); query.addBindValue(tmpStr.m_Three); query.addBindValue(tmpStr.m_One); query.addBindValue(tmpStr.m_Two); query.exec(); errorSQLOrder(query, "update-remark"); QSqlDatabase::database().commit(); if (!query.isActive()) { qDebug() << "QUERY_FAIL::" << query.lastError().text(); m_SqlDatabase->close(); return MT_CHANGE_REMARK_FAIL; } return MT_CHANGE_REMARK_SUCCESS; } int Database::deleteFriend(const QString & myID, const QString & friendID, QString & groupName, QString & groupNameF)//删除好友 { if(!createConnection()) { return MT_DELETE_FRIEND_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); //在groupName下查询分组信息 sqlquery.prepare(SEARCH_GROUPNAME_IN_USERFRIENDS_SQL); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.exec(); errorSQLOrder(sqlquery, "search friend through groupName"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_DELETE_FRIEND_FAIL; } if(sqlquery.next()) { groupName = sqlquery.value(0).toString(); } sqlquery.clear(); //在分组下查询好友groupNameF sqlquery.prepare(SEARCH_GROUPNAME_IN_USERFRIENDS_SQL); sqlquery.addBindValue(friendID); sqlquery.addBindValue(myID); sqlquery.exec(); errorSQLOrder(sqlquery, "search friend through groupNameF"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_DELETE_FRIEND_FAIL; } if(sqlquery.next()) { groupNameF = sqlquery.value(0).toString(); } sqlquery.clear(); //删除好友 sqlquery.prepare(DELETE_FRIEND_IN_USERFRIENDS_SQL); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.addBindValue(friendID); sqlquery.addBindValue(myID); sqlquery.exec(); errorSQLOrder(sqlquery, "delete friends"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_DELETE_FRIEND_FAIL; } return MT_DELETE_FRIEND_SUCCESS; } bool Database::addFriend(const TalkMessage &talMes)//添加好友 { if(!createConnection()) { return false; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(ADD_FRIEND_IN_USERFRIENDS_SQL); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(GROUP_NAME_DEFAULT); sqlquery.exec(); errorSQLOrder(sqlquery, "add friend from sender"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } sqlquery.clear(); sqlquery.prepare(ADD_FRIEND_IN_USERFRIENDS_SQL); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(GROUP_NAME_DEFAULT); sqlquery.exec(); errorSQLOrder(sqlquery, "add friend from recevier"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } QSqlDatabase::database().commit(); return true; } bool Database::insertValuesInDateCounter(const QDate &date)//插入DateCounterb表某日的数据项 { int count = 0; if (!createConnection()) { return false; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(COUNT_DATARECORD_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "count-datecounter"); if(!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if (sqlquery.next()) { count = sqlquery.value(0).toInt(); } if (count == 0) { sqlquery.prepare(INSERT_VALUES_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "insert datecounter"); if (!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if (sqlquery.numRowsAffected() <= 0) //返回受结果SQL语句影响的行数,如果无法确定则返回-1,如果查询未处于活动状态则返回-1 { return false; } } QSqlDatabase::database().commit(); return true; } int Database::getUserTimes(const QDate &date)//获取某日用户注册数量+1=用户ID { int count = 0; if(!insertValuesInDateCounter(QDate::currentDate())) { return 0; } if(!createConnection()) { return 0; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SELECT_USERTIMES_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "select usertimes"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.next()) { count = sqlquery.value(0).toInt(); } QSqlDatabase::database().commit(); return count + 1; } bool Database::increaseUserTimes(const QDate &date)//增加某日用户注册数量 { if(!createConnection()) { return false; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(INCREASE_USERTIMES_IN_DATECOUNTER_SQL); sqlquery.addBindValue(date.toString("yyyy-MM-dd")); sqlquery.exec(); errorSQLOrder(sqlquery, "increase usertimes"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.numRowsAffected() <= 0) { return false; } QSqlDatabase::database().commit(); return true; } int Database::moveFriendToGroup(const QString & myID, const QString & friendID, const QString & title, const QString & newTitle)//移动好友至其他分组 { if(!createConnection()) { return MT_MOVE_FRIEND_BOX_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(MOVE_FRIEND_IN_USERFREINS); sqlquery.addBindValue(title); sqlquery.addBindValue(newTitle); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.exec(); errorSQLOrder(sqlquery, "move friend to group"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_MOVE_FRIEND_BOX_FAIL; } if(sqlquery.numRowsAffected() <= 0) { return MT_MOVE_FRIEND_BOX_FAIL; } QSqlDatabase::database().commit(); return MT_MOVE_FRIEND_BOX_SUCCESS; } int Database::renameGroup(const QString & id, const QString & title, const QString & newTitle)//重命名分组 { if (!createConnection()) { return MT_RENAME_BOX_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(RENAME_GROUPNAME_IN_USERFREINS); sqlquery.addBindValue(newTitle); sqlquery.addBindValue(id); sqlquery.addBindValue(title); sqlquery.exec(); errorSQLOrder(sqlquery, "rename-group"); if (!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return MT_RENAME_BOX_FAIL; } if (sqlquery.numRowsAffected() <= 0) { return MT_RENAME_BOX_FAIL; } QSqlDatabase::database().commit(); return MT_RENAME_BOX_SUCCESS; } bool Database::addHistoryMsg(const TalkMessage &talMes)// 存储历史记录 { if (!createConnection()) { return false; } //sql 事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(INSERT_MESSAGE_IN_HISTORYMESSAGE); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(simplifyRichText(talMes.m_Text)); sqlquery.addBindValue(talMes.m_dateTime); sqlquery.exec(); errorSQLOrder(sqlquery, "inser-mes-to-HistoryMmesage"); if (!sqlquery.isActive()) { qDebug() << "QUERY_FAIL::" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.numRowsAffected() <= 0) { return false; } QSqlDatabase::database().commit(); return true; } bool Database::addOfflineMsg(const TalkMessage &talMes)// 存储离线记录 { if(!createConnection()) { return false; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(INSERT_MESSAGE_IN_OFFLINEMESSAGE); sqlquery.addBindValue(talMes.m_Type); sqlquery.addBindValue(talMes.m_SenderID); sqlquery.addBindValue(talMes.m_ReceiverID); sqlquery.addBindValue(talMes.m_Text); sqlquery.exec(); errorSQLOrder(sqlquery, "insert talmes to offline message"); if(!sqlquery.isActive()) { qDebug() << "QUERY FAIL:" << sqlquery.lastError().text(); m_SqlDatabase->close(); return false; } if(sqlquery.numRowsAffected() <= 0) { return false; } QSqlDatabase::database().commit(); return true; } // 获取用户的某日与某位好友的聊天记录 int Database::searchHistoryMsgOfFriendInDate(const QString & myID, const QString &friendID, const QDate & date, QVector<TalkMessage> & mesVec) { if(!createConnection()) { return MT_GET_HISTORY_MESSAGE_FAIL; } //sql事务 QSqlDatabase::database().transaction(); QSqlQuery sqlquery(*m_SqlDatabase); sqlquery.prepare(SEARCH_FRIEND_DATE_MESSAGE_IN_HISTORYMESSAGE); sqlquery.addBindValue(myID); sqlquery.addBindValue(friendID); sqlquery.addBindValue(date); sqlquery.exec(); errorSQLOrder(sqlquery, "get history msg of friend in oneDay"); QSqlDatabase::database().commit(); if(!sqlquery.isActive()) { m_SqlDatabase->close(); return MT_GET_HISTORY_MESSAGE_FAIL; } mesVec.clear(); //从向量中删除所有元素 while(sqlquery.next()) { TalkMessage talMes; talMes.m_SenderID = sqlquery.value(0).toString(); talMes.m_SenderIP = sqlquery.value(1).toString(); talMes.m_ReceiverID = sqlquery.value(2).toString(); talMes.m_ReceiverIP = sqlquery.value(3).toString(); talMes.m_dateTime = sqlquery.value(4).toDateTime(); talMes.m_Type = sqlquery.value(5).toInt(); talMes.m_Text = sqlquery.value(6).toString(); mesVec.push_back(talMes); //提供此功能是为了实现STL兼容性,等效于append(value) } if(mesVec.isEmpty()) { return MT_NO_MESSAGE; } return MT_GET_HISTORY_MESSAGE_SUCCESS; }

ServerSocket.h

/********************************************* File Name: ServerSocket.h Description: 来自客户端的socket,用于处理各种请求 ********************************************/ #ifndef SERVERSOCKET_H #define SERVERSOCKET_H #include <QTcpSocket> #include "Database.h" #include "Structure.h" class QDateTime; class ServerSocket:public QTcpSocket { Q_OBJECT public: ServerSocket(QObject *parent = nullptr); ~ServerSocket(); signals: // 请求server处理 void sendSignal(const SaveTmpInformation &tmp); // 用户登录 void userLoginSignal(const UserInformation &userInf); //用户断开连接 void deleteSignal(const QString &acc); public slots: // 接收信息 void receiveMessage(); // 发送信息 void sendMessage(const SaveTmpInformation &tmp); // 删除socket void deleteScoket(); private: quint16 m_BlockSize; SaveTmpInformation m_SaveTmpInfo; Database m_Database; }; #endif // SERVERSOCKET_H

ServerSocket.cpp

/********************************************* File Name: ServerSocket.cpp Description: 用于控制客户端socket的类 与客户端连接的QTcpSocket类 ********************************************/ #include "ServerSocket.h" #include <QMultiMap> #include <QDateTime> ServerSocket::ServerSocket(QObject *parent): QTcpSocket(parent) { connect(this, SIGNAL(readyRead()), this, SLOT(receiveMessage())); connect(this, SIGNAL(disconnected()), this, SLOT(deleteScoket())); m_BlockSize = 0; m_SaveTmpInfo.m_ServerSocket = this; } ServerSocket::~ServerSocket() { if (m_Database.isOpen()) m_Database.close(); } void ServerSocket::receiveMessage() //接收用户发送的信息 { QDataStream in(this); in.setVersion(QDataStream::Qt_5_11); //修改QDataStream使用的序列化格式 if(m_BlockSize == 0) { if(bytesAvailable() < (int)sizeof (quint16)) //bytesAvailable()返回等待读取的传入字节数 { return; } in >> m_BlockSize; } if(bytesAvailable() < m_BlockSize) { return; } in >> m_SaveTmpInfo.m_RequestKind; //将临时信息的应答类型输入数据流 qDebug() << "receive message:" << m_SaveTmpInfo.m_RequestKind; switch (m_SaveTmpInfo.m_RequestKind) { case MT_CHECK_CONNECTION: { m_SaveTmpInfo.m_ReplyKind = MT_CHECK_CONNECTION; sendMessage(m_SaveTmpInfo); m_BlockSize = 0; break; } case MT_LOGIN: { in >> m_SaveTmpInfo.m_LoginInf; m_SaveTmpInfo.m_MyID = m_SaveTmpInfo.m_LoginInf.m_UserID; m_SaveTmpInfo.m_SocketID = m_SaveTmpInfo.m_MyID; break; } case MT_CHECK_MESSAGE: { in >> m_SaveTmpInfo.m_MyID; break; } case MT_REGISTER: { in >> m_SaveTmpInfo.m_UserInf; break; } case MT_GET_QUESTION_ANSWER: { in >> m_SaveTmpInfo.m_MyID; break; } case MT_TALK: { in >> m_SaveTmpInfo.m_Message; break; } case MT_GET_ALL_FRIENDS: { in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Status; m_SaveTmpInfo.m_SocketID = m_SaveTmpInfo.m_MyID; break; } case MT_GET_FRIEND_INFORMATION: { in >> m_SaveTmpInfo.m_PeerID; break; } case MT_GET_MYSELF_INFORMATION: { in >> m_SaveTmpInfo.m_MyID; break; } case MT_CHANGE_INFORMATION: { in >> m_SaveTmpInfo.m_UserInf; break; } case MT_CHANGE_REMARK: { in >> m_SaveTmpInfo.m_TempStr; break; } case MT_CHANGE_STATUE: { in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Status; break; } case MT_ADD_FRIEND: { in >> m_SaveTmpInfo.m_Message; break; } case MT_REFUSE_FRIEND: { break; } case MT_DELETE_FRIEND: { in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_PeerID; break; } case MT_REMOVE_BOX: case MT_CREATE_BOX: { in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Title; break; } case MT_MOVE_FRIEND_BOX: { in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_PeerID >> m_SaveTmpInfo.m_Title >> m_SaveTmpInfo.m_NewTitle; break; } case MT_RENAME_BOX: { in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_Title >> m_SaveTmpInfo.m_NewTitle; break; } case MT_GET_HISTORY_MESSAGE: { in >> m_SaveTmpInfo.m_MyID >> m_SaveTmpInfo.m_PeerID >> m_SaveTmpInfo.m_Date; break; } case MT_CHANGE_PASSWORD: { in >> m_SaveTmpInfo.m_TempStr; break; } default: { qDebug() << "Unknow receive msg kind:" << m_SaveTmpInfo.m_RequestKind; break; } } QByteArray data = this->readAll(); //从设备读取所有剩余数据,并将其作为字节数组返回 qDebug() << "leave in socket:" << data.size(); m_BlockSize = 0; emit sendSignal(m_SaveTmpInfo); } void ServerSocket::sendMessage(const SaveTmpInformation &tmp) //发送消息 { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_5_11); out << quint16(0) << (int)tmp.m_ReplyKind; switch(tmp.m_ReplyKind) { case MT_LOGIN_SUCCESS: { out << tmp.m_UserInf; break; } case MT_REGISTER_SUCCESS: { out << tmp.m_UserInf.m_UserID << tmp.m_UserInf.m_HeadPortrait; break; } case MT_GET_QUESTION_ANSWER_SUCCESS: { out << tmp.m_TempStr; break; } case MT_GET_ALL_FRIENDS_SUCCESS: { int len = tmp.m_FriendsVec.size(); out << len; for(int i = 0;i < len;++i) { out << tmp.m_FriendsVec[i]; } break; } case MT_HAVE_MESSAGE: { break; } case MT_CHANGE_STATUE: { out << tmp.m_PeerID << tmp.m_Status; break; } case MT_GET_MYSELF_SUCCESS: { out << tmp.m_UserInf; break; } case MT_DELETE_FRIEND_SUCCESS: { out << tmp.m_MyID << tmp.m_PeerID << tmp.m_GroupName; break; } case MT_CHANGE_INFORMATION_SUCCESS: { out << tmp.m_UserInf; break; } case MT_CHANGE_INFORMATION: { out << tmp.m_FriendInf; break; } case MT_ADD_FRIEND_SUCCESS: { out << tmp.m_Message << tmp.m_UserInf; break; } case MT_GET_FRIEND_SUCCESS: { out << tmp.m_UserInf; break; } case MT_TALK: { out << tmp.m_Message; break; } case MT_CHANGE_REMARK_SUCCESS: { out << tmp.m_TempStr; break; } case MT_BE_DELETED: { out << tmp.m_MyID << tmp.m_PeerID << tmp.m_GroupNameF; break; } case MT_RENAME_BOX_SUCCESS: { out << tmp.m_MyID << tmp.m_Title << tmp.m_NewTitle; break; } case MT_MOVE_FRIEND_BOX_SUCCESS: { out << tmp.m_MyID << tmp.m_PeerID << tmp.m_Title << tmp.m_NewTitle; break; } case MT_GET_HISTORY_MESSAGE_SUCCESS: { out << tmp.m_MyID << tmp.m_PeerID << tmp.m_Date; int len = tmp.m_HistoryMessageVec.size(); out << len; for(int i = 0;i < len;++i) { out << tmp.m_HistoryMessageVec[i]; } break; } default: { qDebug() << "unknown send msg kind:" << m_SaveTmpInfo.m_RequestKind; break; } } //QIODevice *QDataStream::device()返回当前设置的I/O设备,如果当前未设置任何设备,则返回0 out.device()->seek(0);//QIODevice::seek(quint16)将当前位置设为pos,成功返回true,失败返回false out << quint16(block.size() - sizeof(quint16)); write(block); //将数据的最大maxSize字节从数据写入设备,返回实际写入的字节数;如果发生错误,则返回-1 } void ServerSocket::deleteScoket() //删除socket { if(!m_SaveTmpInfo.m_SocketID.isEmpty()) { if(MT_LOGIN != m_SaveTmpInfo.m_RequestKind) { emit deleteSignal(m_SaveTmpInfo.m_SocketID); } deleteLater(); } }

TcpServer.h

/********************************************* File Name: TcpServer.h Description: 服务器类 ********************************************/ #ifndef TCPSERVER_H #define TCPSERVER_H #include <QTcpServer> #include "ServerSocket.h" #include "Structure.h" #include "Database.h" class TcpServer:public QTcpServer { Q_OBJECT public: TcpServer(QObject *parent = nullptr); ~TcpServer(); public slots: //客户端断开连接 void clientDisconnected(const QString &id); //要求ServerSocket发送消息 void sendMessage(const SaveTmpInformation &tmp); signals: void haveNewID(const QString &id); void haveNewAddress(const QString &address); void haveLeftID(const QString &id); void haveLeftAddress(const QString &address); private: // 当有新的连接时,会调用此函数。用于创建新的线程去控制socket通信 void incomingConnection(int socketDescriptor); // 处理好友请求 void friendRequest(const SaveTmpInformation &savTmp); // 处理对话请求 void talkRequest(const SaveTmpInformation &save); // 通知好友,改变用户状态 void tellFriendsStatusChanged(const QString &id, int status); // 通知好友,改变用户信息 void tellFriendsInformationChanged(const QString &id); // 临时信息 SaveTmpInformation m_SaveTmpInfo; // 操作数据库 Database m_Database; // 在线用户列表 QMap<QString, ServerSocket*> m_mapOnlineUser; // 在线用户状态 QMap<QString, int> m_mapOnlineUserStatus; // 邮箱在线的用户 QMap<QString, ServerSocket*> m_mapOnlineUserMail; }; #endif // TCPSERVER_H

TcpServer.cpp

#include "TcpServer.h" TcpServer::TcpServer(QObject *parent) : QTcpServer(parent) { // 初始化一下数据库 } TcpServer::~TcpServer() { } void TcpServer::clientDisconnected(const QString &id) //客户端断开连接 { //某个客户端断开连接时,就更新该用户的状态 if(id.contains(MAIL_ADDRESS_FORMAT))//contains():如果此字符串包含出现的字符串str,则返回true,否则返回false { m_mapOnlineUserMail.remove(id);//remove():返回移除的数量,通常为1,如果键值对不在map内则为0 emit haveLeftAddress(id); } else { m_mapOnlineUser.remove(id); emit haveLeftID(id); if(m_Database.updateStatus(LS_OFFLINE, id)) { tellFriendsStatusChanged(id, LS_OFFLINE); } } #ifdef TEST_SWITCH qDebug() << "userMap-size:" <<m_mapOnlineUser.size(); QMapIterator<QString, ServerSocket*> i(m_mapOnlineUser); while (i.hasNext()) { i.next(); qDebug() << i.key(); } qDebug() << "userMailMap-size:" << m_mapOnlineUserMail.size(); QMapIterator<QString, ServerSocket*> j(m_mapOnlineUser); while(j.hasNext()) { j.next(); qDebug() << j.key(); } #endif } void TcpServer::sendMessage(const SaveTmpInformation &tmp)//处理请求,要求ServerSocket发送信息 { m_SaveTmpInfo.m_RequestKind = tmp.m_RequestKind; //根据tmp.requestKind来处理信息 switch(m_SaveTmpInfo.m_RequestKind) { case MT_LOGIN: { m_SaveTmpInfo.m_LoginInf = tmp.m_LoginInf; m_SaveTmpInfo.m_ServerSocket = tmp.m_ServerSocket; //判断是否已经登录 m_SaveTmpInfo.m_MyID = tmp.m_MyID; if(m_mapOnlineUser.contains(m_SaveTmpInfo.m_MyID)) { m_SaveTmpInfo.m_ReplyKind = MT_HAVE_LOGINED; } else { //访问数据库登录 m_SaveTmpInfo.m_ReplyKind = m_Database.searchUserInUserInformation(m_SaveTmpInfo.m_LoginInf, m_SaveTmpInfo.m_UserInf); } tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_REGISTER://注册 { m_SaveTmpInfo.m_UserInf = tmp.m_UserInf; int count = m_Database.getUserTimes(QDate::currentDate()); if(count == 0) { m_SaveTmpInfo.m_ReplyKind = MT_REGISTER_FAIL; } else { QString id = QDate::currentDate().toString("yyyyMMdd"); id.append(QString::number(0)); id.append(QString::number(count)); m_SaveTmpInfo.m_UserInf.m_UserID = id; m_SaveTmpInfo.m_UserInf.m_RegDateTime = QDateTime::currentDateTime(); //访问数据库注册 m_SaveTmpInfo.m_ReplyKind = m_Database.addUserInUserInformation(m_SaveTmpInfo.m_UserInf); } tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_GET_QUESTION_ANSWER://获得密保问题及答案 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_ReplyKind = m_Database.searchQuestionAndAnswer(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_TempStr); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_CHECK_MESSAGE://检查信息 { break; } case MT_GET_ALL_FRIENDS://获取所有好友 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_Status = tmp.m_Status; m_SaveTmpInfo.m_ServerSocket = tmp.m_ServerSocket; m_SaveTmpInfo.m_ReplyKind = m_Database.searchFriendsInformation(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_FriendsVec); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); if(MT_GET_ALL_FRIENDS_FAIL != m_SaveTmpInfo.m_ReplyKind) { if(!m_mapOnlineUser.contains(m_SaveTmpInfo.m_MyID)) { m_mapOnlineUser.insert(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_ServerSocket); emit haveNewID(m_SaveTmpInfo.m_MyID); } tellFriendsStatusChanged(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_Status); } break; } case MT_TALK://对话请求 { talkRequest(tmp); break; } case MT_CHANGE_INFORMATION://用户改变个人信息 { m_SaveTmpInfo.m_UserInf = tmp.m_UserInf; m_SaveTmpInfo.m_ReplyKind = m_Database.updateMyselfInformation(tmp.m_UserInf); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); if(m_SaveTmpInfo.m_ReplyKind == MT_CHANGE_INFORMATION_SUCCESS) { tellFriendsInformationChanged(m_SaveTmpInfo.m_UserInf.m_UserID); } break; } case MT_GET_MYSELF_INFORMATION://获取个人信息 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_ReplyKind = m_Database.searchMyselfInformationByID(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_UserInf); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_GET_FRIEND_INFORMATION://获取好友信息 { m_SaveTmpInfo.m_PeerID = tmp.m_PeerID; m_SaveTmpInfo.m_ReplyKind = m_Database.searchFriendInformationByID(m_SaveTmpInfo.m_PeerID, m_SaveTmpInfo.m_UserInf); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_DELETE_FRIEND://删除好友 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_PeerID = tmp.m_MyID; m_SaveTmpInfo.m_ReplyKind = m_Database.deleteFriend(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_PeerID, m_SaveTmpInfo.m_GroupName,m_SaveTmpInfo.m_GroupNameF); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); //如果好友在线则发送被删除信息,如果不在线则存储 QMap<QString, ServerSocket*>::iterator iter; //find(const Key &key):返回一个迭代器,该迭代器指向具有键key的项,如果不包含带有该键的项则函数返回end(),如果包含多个带有该键的项则函数返回指向最近插入值的迭代器 iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_PeerID); if(m_mapOnlineUser.end() == iter) //返回一个STL样式的迭代器,该迭代器指向地图中最后一个项目之后的假想项目 { TalkMessage talMes; talMes.m_Type = MT_BE_DELETED; talMes.m_SenderID = tmp.m_MyID; talMes.m_ReceiverID = tmp.m_PeerID; talMes.m_Text = tmp.m_GroupNameF; } else { m_SaveTmpInfo.m_MyID = tmp.m_PeerID; m_SaveTmpInfo.m_PeerID = tmp.m_MyID; m_SaveTmpInfo.m_ReplyKind = MT_BE_DELETED; m_SaveTmpInfo.m_GroupName = tmp.m_GroupNameF; //T &iterator::value() const,返回对当前项目值的可修改引用 iter.value()->sendMessage(m_SaveTmpInfo); } break; } case MT_CHANGE_REMARK://修改个签 { m_SaveTmpInfo.m_TempStr = tmp.m_TempStr; m_SaveTmpInfo.m_ReplyKind = m_Database.updateRemark(tmp.m_TempStr); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_ADD_FRIEND://添加好友 { friendRequest(tmp); break; } case MT_CHANGE_STATUE://改变在线状态 { if(m_Database.updateStatus(tmp.m_Status, tmp.m_MyID)) { tellFriendsStatusChanged(tmp.m_MyID, tmp.m_Status); } break; } case MT_REMOVE_BOX://删除分组 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_Title = tmp.m_Title; break; } case MT_CREATE_BOX://创建分组 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_Title = tmp.m_Title; break; } case MT_MOVE_FRIEND_BOX://移动好友至其他分组 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_Title = tmp.m_Title; m_SaveTmpInfo.m_PeerID = tmp.m_PeerID; m_SaveTmpInfo.m_NewTitle = tmp.m_NewTitle; m_SaveTmpInfo.m_ReplyKind = m_Database.moveFriendToGroup(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_PeerID, m_SaveTmpInfo.m_Title, m_SaveTmpInfo.m_NewTitle); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_RENAME_BOX://分组重命名 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_Title = tmp.m_Title; m_SaveTmpInfo.m_NewTitle = tmp.m_NewTitle; m_SaveTmpInfo.m_ReplyKind = m_Database.renameGroup(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_Title, m_SaveTmpInfo.m_NewTitle); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_GET_HISTORY_MESSAGE://读取某天与某好友的消息历史记录 { m_SaveTmpInfo.m_MyID = tmp.m_MyID; m_SaveTmpInfo.m_PeerID = tmp.m_PeerID; m_SaveTmpInfo.m_Date = tmp.m_Date; m_SaveTmpInfo.m_ReplyKind = m_Database.searchHistoryMsgOfFriendInDate(m_SaveTmpInfo.m_MyID, m_SaveTmpInfo.m_PeerID, m_SaveTmpInfo.m_Date, m_SaveTmpInfo.m_HistoryMessageVec); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } case MT_CHANGE_PASSWORD://修改密码 { m_SaveTmpInfo.m_TempStr = tmp.m_TempStr; m_SaveTmpInfo.m_ReplyKind = m_Database.updatePassword(m_SaveTmpInfo.m_TempStr); tmp.m_ServerSocket->sendMessage(m_SaveTmpInfo); break; } default: { break; } } } void TcpServer::incomingConnection(int socketDescriptor) //当有新的连接时,会调用此函数,用于创建新的线程去控制socket通信 { //建立新连接,并链接相关的信号和槽 ServerSocket *serverSocket = new ServerSocket(this); serverSocket->setSocketDescriptor(socketDescriptor); connect(serverSocket, SIGNAL(deleteSignal(const QString&)), this, SLOT(clientDisconnected(const QString&))); connect(serverSocket, SIGNAL(sendSignal(const SaveTmpInformation&)), this, SLOT(sendMessage(const SaveTmpInformation&))); qDebug() << "new client IP:" << serverSocket->peerAddress(); qDebug() << "userMap-size:" << m_mapOnlineUser.size(); #ifdef TEST_SWITCH QMapIterator<QString, ServerSocket *> i(m_mapOnlineUser); while (i.hasNext()) { i.next(); qDebug() << i.key(); } qDebug() << "userMailMap-size:" << m_mapOnlineUserMail.size(); QMapIterator<QString, ServerSocket *> j(m_mapOnlineUserMail); while (j.hasNext()) { j.next(); qDebug() << j.key(); } #endif } void TcpServer::friendRequest(const SaveTmpInformation &savTmp) //处理好友申请请求 { m_SaveTmpInfo.m_ReplyKind = MT_ADD_FRIEND; m_SaveTmpInfo.m_Message = savTmp.m_Message; switch(savTmp.m_Message.m_Type) { case MT_REQUEST_FRIEND: { if(MT_ADD_FRIEND_SUCCESS != m_Database.searchFriendInformationByID(m_SaveTmpInfo.m_Message.m_SenderID, m_SaveTmpInfo.m_UserInf)) { return; } qDebug() << "request add friend"; break; } case MT_REFUSE_FRIEND: { qDebug() << "refuse add friend"; break; } case MT_AGREE_FRIEND: { if(!m_Database.addFriend(m_SaveTmpInfo.m_Message)) { m_SaveTmpInfo.m_Message.m_Type = MT_ADD_FRIEND_FAIL; break; } m_SaveTmpInfo.m_Message.m_SenderID = savTmp.m_Message.m_ReceiverID; m_SaveTmpInfo.m_Message.m_ReceiverID = savTmp.m_Message.m_SenderID; if(MT_GET_FRIEND_SUCCESS != m_Database.searchFriendInformationByID(m_SaveTmpInfo.m_Message.m_SenderID, m_SaveTmpInfo.m_UserInf)) { m_SaveTmpInfo.m_Message.m_Type = MT_ADD_FRIEND_FAIL; return; } qDebug() << "agree add friend"; break; } default: { return; } } QMap<QString, ServerSocket*>::iterator iter; iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_Message.m_ReceiverID); if(m_mapOnlineUser.end() == iter) { //save offline msg } else { iter.value()->sendMessage(m_SaveTmpInfo); } } void TcpServer::talkRequest(const SaveTmpInformation &savTmp) //处理对话请求 { m_SaveTmpInfo.m_Message = savTmp.m_Message; switch(m_SaveTmpInfo.m_Message.m_Type) { case MT_TALK_MESSAGE: { m_SaveTmpInfo.m_ReplyKind = MT_TALK; QMap<QString, ServerSocket*>::iterator iter; iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_Message.m_ReceiverID); //聊天记录存储到数据库 m_Database.addHistoryMsg(m_SaveTmpInfo.m_Message); if(m_mapOnlineUser.end() == iter) { //存储离线消息到数据库 m_Database.addOfflineMsg(m_SaveTmpInfo.m_Message); } else { iter.value()->sendMessage(m_SaveTmpInfo); } break; } default: { break; } } } void TcpServer::tellFriendsStatusChanged(const QString &id, int status) //通知好友,改变用户状态 { m_SaveTmpInfo.m_ReplyKind = MT_CHANGE_STATUE; m_SaveTmpInfo.m_Status = status; m_SaveTmpInfo.m_PeerID = id; m_Database.searchFriendsID(id, m_SaveTmpInfo.m_IDVec); QMap<QString, ServerSocket*>::iterator iter; for(int i = 0;i < m_SaveTmpInfo.m_IDVec.size();i++) { iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_IDVec[i]); if(iter != m_mapOnlineUser.end()) { iter.value()->sendMessage(m_SaveTmpInfo); } } } void TcpServer::tellFriendsInformationChanged(const QString &id) //通知好友,改变用户信息 { m_SaveTmpInfo.m_ReplyKind = MT_CHANGE_INFORMATION; if(!m_Database.searchFriendsID(id, m_SaveTmpInfo.m_IDVec)) { return; } m_SaveTmpInfo.m_FriendInf.m_HeadPortrait = m_SaveTmpInfo.m_UserInf.m_HeadPortrait; m_SaveTmpInfo.m_FriendInf.m_NickName = m_SaveTmpInfo.m_UserInf.m_NickName; m_SaveTmpInfo.m_FriendInf.m_UserID = m_SaveTmpInfo.m_UserInf.m_UserID; m_SaveTmpInfo.m_FriendInf.m_Status = m_SaveTmpInfo.m_UserInf.m_Status; QMap<QString, ServerSocket*>::iterator iter; for(int i = 0;i < m_SaveTmpInfo.m_IDVec.size();i++) { iter = m_mapOnlineUser.find(m_SaveTmpInfo.m_IDVec[i]); if(iter != m_mapOnlineUser.end()) { iter.value()->sendMessage(m_SaveTmpInfo); } } }
最新回复(0)