如果客户端异常退出了,我们会从服务端记录用户连接的 _connMap
表中找到改用户,如果它断连了就从此表中删除,并设置其状态为 offline
。
因为记录用户连接情况的表是可能被多个线程操作的,所以访问表的操作都要使用互斥锁进行保护。
// 处理客户端异常退出
void ChatService::clientCloseExceptionHandler(const TcpConnectionPtr &conn)
{
User user;
// 互斥锁保护
{
lock_guard<mutex> lock(_connMutex);
for (auto it = _userConnMap.begin(); it != _userConnMap.end(); ++it)
{
if (it->second == conn)
{
// 从map表删除用户的链接信息
user.setId(it->first);
_userConnMap.erase(it);
break;
}
}
}
// 用户注销
_redis.unsubscribe(user.getId());
// 更新用户的状态信息
if (user.getId() != -1)
{
user.setState("offline");
_userModel.updateState(user);
}
}
客户端异常退出模块测试
我们先登录用户张三
可以看到数据库显示张三用户是登录的状态
我们使用CTRL + C
键模拟客户端异常退出,然后查看数据库情况。可以看到服务端监听到了客户端连接断开的情况,并打印日志。
数据库情况,可以看到断连用户状态被重置为offline
。