博客网址:www.shicoder.top
微信:kj11011029
欢迎加群聊天 :452380935
本篇文章主要实现了聊天服务器中一对一聊天和添加好友功能
一对一聊天
以下是聊天对应的json
字符串格式
{"msgid":5,"id":2,"from":"lisi","to":1,"msg":"hello4"}
同样在ChatService
中添加如下函数
// 一对一聊天业务
void oneChat(const TcpConnectionPtr &conn, json &js, Timestamp);
注意:锁的处理
在一对一聊天中,我们需要服务器知道哪些用户是在线的,哪些用户是离线的,对于在线用户,我们直接将聊天信息转发,对于离线好友,我们需要将信息先存储在离线信息表中,然后等对方在线后,再进行发送。所以我们采用一个map
来保存userid
和conn
的对应关系
// 存储在线用户的连接,因为比如用户1向用户2发送请求,这时候需要服务器来做中间转化
// 所以服务器需要知道用户2是否在线
unordered_map<int, TcpConnectionPtr> _userConnMap;
这样在用户登陆的时候,若登陆成功,需要给当前用户的userid
添加一个conn
的map
键值对,同时利用锁进行处理,防止出现意外。
// 在这里加{}主要就是设置作用域,lock_guard<mutex> lock(_connMutex)中lock_guard会在构造函数加锁,
// 析构函数释放锁,同时由于只需要insert需要锁,所以加一个作用域,这样避免给不必要的地方加锁,浪费资源
{
lock_guard<mutex> lock(_connMutex);
// 记录用户连接信息
_userConnMap.insert({id, conn});
}
//登陆成功,然后更新用户登陆信息
user.setState("online");
_usermodel.updateState(user);
json response;
response["msgid"] = LOGIN_MSG_ACK;
response["error"] = 0; //0表示成功
response["id"] = user.getId();
response["name"] = user.getName();
这样采用如下代码实现消息的转发或者消息的存储
// 一对一聊天业务
void ChatService::oneChat(const TcpConnectionPtr &conn, json &js, Timestamp)
{
// 对方id
int toid = js["to"].get<int>();
{
lock_guard<mutex> lock(_connMutex);
auto it = _userConnMap.find(toid);
if (it != _userConnMap.end())
{
// toid在线,转发消息
it->second->send(js.dump());
return;
}
}
// 不在线,存储离线消息
_offlinemodel.insert(toid, js.dump());
}
对于离线好友,我们需要在他登陆的时候,首先去查询_offlinemodel
这个map
中是否有自己对应的离线消息,若有,要先让服务器推送消息给用户,然后从map
中删除对应的消息
注意,我在这里暂时打算让服务器用一个vector<string>
存储离线消息
// 查询该用户是否有离线信息
vector<string> vec = _offlinemodel.query(id);
if (!vec.empty())
{
response["offlinemsg"] = vec;
// 再删除离线消息
_offlinemodel.remove(id);
}
添加好友
以下是添加好友的json字符串
{"msgid":6,"id":1,"friendid":2}
同样在ChatService
中添加如下代码
// 添加好友请求 msgid id friendid
void ChatService::addFriend(const TcpConnectionPtr &conn, json &js, Timestamp)
{
int userid = js["id"].get<int>();
int friendid = js["friendid"].get<int>();
// 存储好友信息
_friendmodel.insert(userid, friendid);
}
首先需要在用户登陆的时候,服务器自动推送给用户其对应的好友,所以需要一个vector<User>
来存储该用户对应的好友列表,同时将这个vector
和userid
在数据库中保存,表结构如下
字段名称 | 字段类型 | 字段说明 | 约束 |
---|---|---|---|
userid | INT | 用户id | NOT NULL、联合主键 |
friendid | INT | 好友id | NOT NULL、联合主键 |
在用户登录成功之后,服务器会去查询用户的好友列表,然后推送给用户,其代码如下:
// 查询该用户的好友信息 并返回
vector<User> uservec = _friendmodel.query(id);
if (!uservec.empty())
{
vector<string> vec2;
for (auto &i : uservec)
{
json js;
js["id"] = i.getId();
js["name"] = i.getName();
js["state"] = i.getState();
vec2.emplace_back(js.dump());
}
response["friends"] = vec2;
}
其中的_friendmodel.query()
使用的是多表联合查询,sql
语句为
select a.id,a.name,a.state from user a inner join friend b on b.friendid = a.id where b.userid = %d
下一章我们实现下群组的创建与群组之间的聊天业务。
想想你的文章写的特别好
叼茂SEO.bfbikes.com
不错不错,我喜欢看 https://www.237fa.com/
想想你的文章写的特别好https://www.ea55.com/
看的我热血沸腾啊www.jiwenlaw.com
文章的确不错啊https://www.cscnn.com/
《世界奇妙物语 2013年秋之特别篇》恐怖片高清在线免费观看:https://www.jgz518.com/xingkong/35000.html
博主太厉害了!
独家揭秘:传奇私服惊天花屏现象,揭秘背后神秘真相!:https://501h.com/jinbi/2024-10-27/45270.html
《女演员大作战》喜剧片高清在线免费观看:https://www.jgz518.com/xingkong/97554.html
《High Kick 短腿的反击》韩国剧高清在线免费观看:https://www.jgz518.com/xingkong/57473.html
《魂断加尔各答》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/5818.html
《我的燃情岁月》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/34210.html
《High Kick 短腿的反击》韩国剧高清在线免费观看:https://www.jgz518.com/xingkong/57473.html
《异能男友》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/17035.html
《暗界之主》短片剧高清在线免费观看:https://www.jgz518.com/xingkong/26038.html