C++项目 | 集群聊天服务器 | 添加好友业务 添加好友后,每次用户登录会返回离线消息和好友列表
这里的添加好友功能就是单方面的,我只要通过你的id加上你,就是加上了,不用同意或者拒绝
1.数据库层的封装 friend表:
friendmodel.hpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #ifndef FRIENDMODEL_H #define FRIENDMODEL_H #include <vector> #include "user.hpp" using namespace std;class FriendModel { public : void insert (int userid,int frinedid) ; vector<User> query (int userid) ; }; #endif
friendmodel.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include "friendmodel.hpp" #include "db.h" void FriendModel::insert (int userid,int frinedid) { char sql[1024 ]={0 }; sprintf (sql,"insert into friend values(%d,%d)" ,userid,frinedid); MySQL mysql; if (mysql.connect ()) { mysql.update (sql); } } vector<User> FriendModel::query (int userid) { char sql[1024 ]={0 }; sprintf (sql,"select a.id,a.name,a.state from user a inner join friend b on b.friendid=a.id where b.userid = %d" ,userid); vector<User> vec; MySQL mysql; if (mysql.connect ()) { MYSQL_RES *res=mysql.query (sql); if (res!=nullptr ) { MYSQL_ROW row; while ((row=mysql_fetch_row (res))!=nullptr ) { User user; user.setId (atoi (row[0 ])); user.setName (row[1 ]); user.setState (row[2 ]); vec.push_back (user); } mysql_free_result (res); return vec; } } return vec; }
sql语句说明
1 select a.id,a.name,a.state from user a inner join friend b on b.friendid= a.id where b.userid = % d
User和Friend两表联合查询,
2.添加数据库操作对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ChatService { public : static ChatService* instance () ; void login (const TcpConnectionPtr& conn,json &js,Timestamp time) ; void reg (const TcpConnectionPtr& conn,json &js,Timestamp time) ; void oneChat (const TcpConnectionPtr& conn,json &js,Timestamp time) ; void addFriend (const TcpConnectionPtr& conn,json &js,Timestamp time) ; MsgHandler getHandler (int msgid) ; void clientCloseExecption (const TcpConnectionPtr &conn) ; void reset () ; private : ChatService (); unordered_map<int ,MsgHandler> _msgHandlerMap; mutex _connMutex; unordered_map<int ,TcpConnectionPtr> _userConnMap; UserModel _userModel; OfflineMsgModel _offlineMsgModel; FriendModel _friendModel; };
3.注册绑定相应的处理器handler 1 2 3 4 5 6 7 8 ChatService::ChatService () { _msgHandlerMap.insert ({LOGIN_MSG,std::bind (&ChatService::login,this ,_1,_2,_3)}); _msgHandlerMap.insert ({REG_MSG,std::bind (&ChatService::reg,this ,_1,_2,_3)}); _msgHandlerMap.insert ({ONE_CHAT_MSG,std::bind (&ChatService::oneChat,this ,_1,_2,_3)}); _msgHandlerMap.insert ({ADD_FRIEND_MSG,std::bind (&ChatService::addFriend,this ,_1,_2,_3)}); }
4.返回好友列表 新增部分是45-58行,处理用户登录后进行返回好友列表的操作的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 void ChatService::login (const TcpConnectionPtr& conn,json &js,Timestamp time) { int id=js["id" ].get <int >(); string pwd=js["password" ]; User user=_userModel.query (id); if (user.getId ()==id && user.getPwd ()==pwd) { if (user.getState ()=="online" ) { json response; response["msgid" ]=LOGIN_MSG_ACK; response["errno" ]=2 ; response["errmsg" ]="该用户已经登录,请重新输入新账号" ; conn->send (response.dump ()); } else { { lock_guard<mutex> lock (_connMutex); _userConnMap.insert ({id,conn}); } user.setState ("online" ); _userModel.updateState (user); json response; response["msgid" ]=LOGIN_MSG_ACK; response["errno" ]=0 ; response["id" ]=user.getId (); response["name" ]=user.getName (); vector<string> vec=_offlineMsgModel.query (id); if (!vec.empty ()) { response["offlinemsg" ]=vec; _offlineMsgModel.remove (id); } vector<User> userVec=_friendModel.query (id); if (!userVec.empty ()) { vector<string> vec2; for (User &user:userVec) { json js; js["id" ]=user.getId (); js["name" ]=user.getName (); js["state" ]=user.getState (); vec2. push_back (js.dump ()); } response["friends" ]=vec2; } conn->send (response.dump ()); } } else { json response; response["msgid" ]=LOGIN_MSG_ACK; response["errno" ]=1 ; response["errmsg" ]="用户名或者密码错误" ; conn->send (response.dump ()); } } void ChatService::reg (const TcpConnectionPtr& conn,json &js,Timestamp time) { string name=js["name" ]; string pwd=js["password" ]; User user; user.setName (name); user.setPwd (pwd); bool state=_userModel.insert (user); if (state) { json response; response["msgid" ]=REG_MSG_ACK; response["errno" ]=0 ; response["id" ]=user.getId (); conn->send (response.dump ()); } else { json response; response["msgid" ]=REG_MSG_ACK; response["errno" ]=1 ; conn->send (response.dump ()); } }
1 2 3 4 5 { "msgid" : 1 , "id" : 1 , "password" : "123456" } { "msgid" : 6 , "id" : 1 , "friendid" : 2 }