TeamTalk消息服务器(群组相关)

具体的流程如下介绍,后续需要着重研究数据库相关表的结构设计。

群组信令和协议设计

enum GroupCmdID {CID_GROUP_NORMAL_LIST_REQUEST = 1025,CID_GROUP_NORMAL_LIST_RESPONSE = 1026,CID_GROUP_INFO_REQUEST = 1027,CID_GROUP_INFO_RESPONSE = 1028,// ...... 暂时省略无关信令
};message IMNormalGroupListReq{//cmd id:			0x0401required uint32 user_id = 1;optional bytes attach_data = 20;
}message IMNormalGroupListRsp{//cmd id:			0x0402required uint32 user_id = 1;repeated IM.BaseDefine.GroupVersionInfo group_version_list = 2;optional bytes attach_data = 20;
}message GroupVersionInfo{required uint32 group_id = 1;required uint32 version = 2; // 不同级别的群??	
}message IMGroupInfoListReq{//cmd id:			0x0403required uint32 user_id = 1; // 用户IDrepeated IM.BaseDefine.GroupVersionInfo group_version_list = 2; // 群ID列表optional bytes attach_data = 20;
}message IMGroupInfoListRsp{//cmd id:			0x0404required uint32 user_id = 1;repeated IM.BaseDefine.GroupInfo group_info_list = 2;optional bytes attach_data = 20;
}message GroupInfo{required uint32 group_id = 1;required uint32 version = 2;required string group_name = 3;required string group_avatar = 4;required uint32 group_creator_id = 5;required GroupType group_type = 6;required uint32 shield_status = 7;		//1: shield  0: not shield repeated uint32 group_member_list = 8;
}

请求用户群组ID

流程图

请添加图片描述

具体代码逻辑

db_proxy_server 收到 CID_GROUP_NORMAL_LIST_REQUEST后调用 DB_PROXY::getNormalGroupList 函数
主要就是读取用户ID所在群的ID列表

// group
m_handler_map.insert(make_pair(uint32_t(CID_GROUP_NORMAL_LIST_REQUEST), DB_PROXY::getNormalGroupList));/***  获取正式群列表**  @param pPdu      收到的packet包指针*  @param conn_uuid 该包过来的socket 描述符*/
void getNormalGroupList(CImPdu* pPdu, uint32_t conn_uuid)
{IM::Group::IMNormalGroupListReq msg;IM::Group::IMNormalGroupListRsp msgResp;if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())){CImPdu* pPduRes = new CImPdu;uint32_t nUserId = msg.user_id();list<IM::BaseDefine::GroupVersionInfo> lsGroup;// 关键函数CGroupModel::getInstance()->getUserGroup(nUserId, lsGroup, IM::BaseDefine::GROUP_TYPE_NORMAL);msgResp.set_user_id(nUserId);for(auto it=lsGroup.begin(); it!=lsGroup.end(); ++it){IM::BaseDefine::GroupVersionInfo* pGroupVersion = msgResp.add_group_version_list();pGroupVersion->set_group_id(it->group_id());pGroupVersion->set_version(it->version());}log("getNormalGroupList. userId=%u, count=%d", nUserId, msgResp.group_version_list_size());msgResp.set_attach_data(msg.attach_data());pPduRes->SetPBMsg(&msgResp);pPduRes->SetSeqNum(pPdu->GetSeqNum());pPduRes->SetServiceId(IM::BaseDefine::SID_GROUP);pPduRes->SetCommandId(IM::BaseDefine::CID_GROUP_NORMAL_LIST_RESPONSE);CProxyConn::AddResponsePdu(conn_uuid, pPduRes);}else{log("parse pb failed");}
}void CGroupModel::getUserGroup(uint32_t nUserId, list<IM::BaseDefine::GroupVersionInfo>& lsGroup, uint32_t nGroupType)
{list<uint32_t> lsGroupId;getUserGroupIds(nUserId, lsGroupId,0);if(lsGroupId.size() != 0){getGroupVersion(lsGroupId, lsGroup, nGroupType);}
}void CGroupModel::getUserGroupIds(uint32_t nUserId, list<uint32_t>& lsGroupId, uint32_t nLimited)
{CDBManager* pDBManager = CDBManager::getInstance();CDBConn* pDBConn = pDBManager->GetDBConn("teamtalk_slave");if(pDBConn){string strSql ;if (nLimited != 0) {strSql = "select groupId from IMGroupMember where userId=" + int2string(nUserId) + " and status = 0 order by updated desc, id desc limit " + int2string(nLimited);}else{strSql = "select groupId from IMGroupMember where userId=" + int2string(nUserId) + " and status = 0 order by updated desc, id desc";}CResultSet* pResultSet = pDBConn->ExecuteQuery(strSql.c_str());if(pResultSet){while(pResultSet->Next()){uint32_t nGroupId = pResultSet->GetInt("groupId");lsGroupId.push_back(nGroupId);}delete pResultSet;}else{log("no result set for sql:%s", strSql.c_str());}pDBManager->RelDBConn(pDBConn);}else{log("no db connection for teamtalk_slave");}
}

请求用户群组具体信息

流程图

请添加图片描述

具体代码逻辑

DB_PROXY::getGroupInfo函数主要做:

  1. 解析user_id,解析群ID列表
  2. 根据群ID 通过 redis 缓存查找读取群成员列表
  3. 根据群ID通过数据库查找IMGroup 表获取对应群的详细信息
  4. 组包群信息以及群成员列表
// group
m_handler_map.insert(make_pair(uint32_t(CID_GROUP_INFO_REQUEST), DB_PROXY::getGroupInfo));/***  获取群信息**  @param pPdu      收到的packet包指针*  @param conn_uuid 该包过来的socket 描述符*/
void getGroupInfo(CImPdu* pPdu, uint32_t conn_uuid)
{IM::Group::IMGroupInfoListReq msg;IM::Group::IMGroupInfoListRsp msgResp;if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())){CImPdu* pPduRes = new CImPdu;uint32_t nUserId = msg.user_id();uint32_t nGroupCnt = msg.group_version_list_size();map<uint32_t, IM::BaseDefine::GroupVersionInfo> mapGroupId;for(uint32_t i=0; i<nGroupCnt; ++i){IM::BaseDefine::GroupVersionInfo groupInfo = msg.group_version_list(i);// redisif(CGroupModel::getInstance()->isValidateGroupId(groupInfo.group_id())){mapGroupId[groupInfo.group_id()] = groupInfo;}}list<IM::BaseDefine::GroupInfo> lsGroupInfo;CGroupModel::getInstance()->getGroupInfo(mapGroupId, lsGroupInfo);msgResp.set_user_id(nUserId);for(auto it=lsGroupInfo.begin(); it!=lsGroupInfo.end(); ++it){IM::BaseDefine::GroupInfo* pGroupInfo = msgResp.add_group_info_list();pGroupInfo->set_group_id(it->group_id());pGroupInfo->set_version(it->version());pGroupInfo->set_group_name(it->group_name());pGroupInfo->set_group_avatar(it->group_avatar());pGroupInfo->set_group_creator_id(it->group_creator_id());pGroupInfo->set_group_type(it->group_type());pGroupInfo->set_shield_status(it->shield_status());uint32_t nGroupMemberCnt = it->group_member_list_size();for (uint32_t i=0; i<nGroupMemberCnt; ++i) {uint32_t userId = it->group_member_list(i);pGroupInfo->add_group_member_list(userId);}}log("userId=%u, requestCount=%u", nUserId, nGroupCnt);msgResp.set_attach_data(msg.attach_data());pPduRes->SetPBMsg(&msgResp);pPduRes->SetSeqNum(pPdu->GetSeqNum());pPduRes->SetServiceId(IM::BaseDefine::SID_GROUP);pPduRes->SetCommandId(IM::BaseDefine::CID_GROUP_INFO_RESPONSE);CProxyConn::AddResponsePdu(conn_uuid, pPduRes);}else{log("parse pb failed");}
}// redis
bool CGroupModel::isValidateGroupId(uint32_t nGroupId)
{bool bRet = false;CacheManager* pCacheManager = CacheManager::getInstance();CacheConn* pCacheConn = pCacheManager->GetCacheConn("group_member");if(pCacheConn){string strKey = "group_member_"+int2string(nGroupId);bRet = pCacheConn->isExists(strKey);pCacheManager->RelCacheConn(pCacheConn);}return bRet;
}// mysql
void CGroupModel::getGroupInfo(map<uint32_t,IM::BaseDefine::GroupVersionInfo>& mapGroupId, list<IM::BaseDefine::GroupInfo>& lsGroupInfo)
{ if (!mapGroupId.empty()){CDBManager* pDBManager = CDBManager::getInstance();CDBConn* pDBConn = pDBManager->GetDBConn("teamtalk_slave");if (pDBConn){string strClause;bool bFirst = true;for(auto it=mapGroupId.begin(); it!=mapGroupId.end(); ++it){if(bFirst){bFirst = false;strClause = int2string(it->first);}else{strClause += ("," + int2string(it->first));}}string strSql = "select * from IMGroup where id in (" + strClause  + ") order by updated desc";CResultSet* pResultSet = pDBConn->ExecuteQuery(strSql.c_str());if(pResultSet){while (pResultSet->Next()) {uint32_t nGroupId = pResultSet->GetInt("id");uint32_t nVersion = pResultSet->GetInt("version");if(mapGroupId[nGroupId].version() < nVersion){IM::BaseDefine::GroupInfo cGroupInfo;cGroupInfo.set_group_id(nGroupId);cGroupInfo.set_version(nVersion);cGroupInfo.set_group_name(pResultSet->GetString("name"));cGroupInfo.set_group_avatar(pResultSet->GetString("avatar"));IM::BaseDefine::GroupType nGroupType = IM::BaseDefine::GroupType(pResultSet->GetInt("type"));if(IM::BaseDefine::GroupType_IsValid(nGroupType)){cGroupInfo.set_group_type(nGroupType);cGroupInfo.set_group_creator_id(pResultSet->GetInt("creator"));lsGroupInfo.push_back(cGroupInfo);}else{log("invalid groupType. groupId=%u, groupType=%u", nGroupId, nGroupType);}}}delete pResultSet;}else{log("no result set for sql:%s", strSql.c_str());}pDBManager->RelDBConn(pDBConn);if(!lsGroupInfo.empty()){fillGroupMember(lsGroupInfo);}}else{log("no db connection for teamtalk_slave");}}else{log("no ids in map");}
}

最近联系会话信令和协议设计

enum BuddyListCmdID {CID_BUDDY_LIST_RECENT_CONTACT_SESSION_REQUEST = 513,CID_BUDDY_LIST_RECENT_CONTACT_SESSION_RESPONSE = 514,// ...... 暂时省略无关信令CID_BUDDY_LIST_USERS_STATUS_REQUEST = 522,CID_BUDDY_LIST_USERS_STATUS_RESPONSE = 523,// ...... 暂时省略无关信令
};

获取最近联系会话

流程图

具体代码逻辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1523444.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】一文详细向您介绍 bisect_left 函数

【Python】一文详细向您介绍 bisect_left 函数 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&#x…

项目管理:项目经理如何才能做好时间管理?

在项目管理中&#xff0c;时间管理是至关重要的环节。作为项目经理&#xff0c;有效的时间管理不仅关乎个人工作效率&#xff0c;更直接影响到项目的整体进度、成本控制和质量保证。 以下是一些建议&#xff0c;帮助项目经理更好地进行时间管理&#xff1a; 一、明确项目目标…

做Ozon的挣钱逻辑,选择高客单高利润的4点原因

以下是选择高客单高利润产品在 Ozon 上销售的四点原因&#xff1a; 一、利润空间更可观 高客单价产品单个利润高&#xff1a;比如销售一件高客单价的高端电子产品&#xff0c;其利润可能是低客单价产品的数倍甚至更多。假设一件低客单价的普通日用品利润为 5 元&#xff0c;而…

2024年9月7日(星期六)骑行滑草场

2024年9月7日 (星期六) 骑行滑草场&#xff0c;早8:30到9:00&#xff0c; 郊野公园西门集合&#xff0c;9:00准时出发【因迟到者&#xff0c;骑行速度快者&#xff0c;可自行追赶偶遇。】 偶遇地点:郊野公园西门集合 &#xff0c;家住东&#xff0c;南&#xff0c;北的骑友在…

护眼灯真的可以保护眼睛吗?曝光劣质护眼台灯常见的三个特征

护眼灯真的可以保护眼睛吗&#xff1f;随着时代的发展&#xff0c;我们注意到越来越多的孩子开始佩戴眼镜。这一趋势引起了许多细心家长的关注&#xff0c;他们认识到这不仅是个别情况&#xff0c;而是现代生活方式和环境对孩子视力健康的挑战。自然而然地&#xff0c;“儿童是…

springboot名著阅读网站

基于 springbootvue实现的名著阅读网站&#xff08;源码L文ppt&#xff09;4-035 4 系统设计 4.1 系统概述 名著阅读网站的设计与开发是指对该系统的各个功能模块进行详细设计&#xff0c;力求每个模块都能够满足用户的要求&#xff0c;系统开发完成后还需对系统进行单元…

C语言 ——— #define 定义宏

目录 何为宏 宏的声明及其使用方式 宏中的括号是否多余 何为宏 #define 机制包括了一个规定&#xff0c;允许把参数替换到文本中&#xff0c;这种实现通常称宏 宏的声明及其使用方式 声明代码演示&#xff1a; #define MAX(x,y) ((x)>(y)?(x):(y)) 使用代码演示&a…

第66期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

xxe漏洞靶场实战通过

1、用nmap扫描C段&#xff0c;找到靶场 2、打开网址&#xff0c;查看robots.txt文件 3、发现有两个目录&#xff0c;分别查看发现一个登录页面 4、使用BP抓包&#xff0c;发现是xml类型 5、尝试查看/etc/passwd 文件&#xff0c;在尝试查看xxe.php文件&#xff0c;发现是编码后…

VXLAN 为何采用UDP

VXLAN 简介 VXLAN是一种网络虚拟化技术&#xff0c;它通过在UDP数据包中封装MAC地址和IP信息&#xff0c;使得二层网络&#xff08;如以太网&#xff09;能够跨越三层网络&#xff08;如IP网络&#xff09;进行扩展。这种封装方式不仅支持TCP流量的传输&#xff0c;还能有效处…

合宙LuatOS开发板Core_Air780EP使用说明

Core-Air780EP 开发板是合宙通信推出的基于 Air780EP 模组所开发的&#xff0c; 包含电源&#xff0c;SIM卡&#xff0c;USB&#xff0c;天线&#xff0c;音频等必要功能的最小硬件系统。 以方便用户在设计前期对 Air780EP模块进行性能评估&#xff0c;功能调试&#xff0c;软…

辞职一年赚了50w才知道:上班真的不赚钱。

不知不觉就进入九月了&#xff0c;一年一度的苹果秋季发布会又准备开始了。 听说今年iPhone系列有重磅升级&#xff0c;会搭载苹果智能 「Apple Intelligence」&#xff0c;搓搓手等着以旧换新了&#xff01; 此前iPhone15 pro max系列用户已经可以享受部分AI功能&#xff0c;…

【C++模板初阶】

文章目录 一、泛型编程二、函数模板1.函数模板概念2.函数模板格式3.函数模板的原理4 函数模板的实例化1. 隐式实例化2. 显式实例化不同类型形参传参时的处理 5.模板参数的匹配原则 三、类模板1 类模板的定义格式2 类模板的实例化 一、泛型编程 首先大家先思考一个问题&#xff…

文字转视频软件哪个好用?揭秘创意新工具

最近&#xff0c;我在筹备一个小型的个人项目&#xff0c;需要制作一系列的教学视频&#xff0c;但我对视频编辑一窍不通。就在我快要放弃的时候&#xff0c;我发现了一些神奇的工具&#xff0c;它们能自动把文字变成视频&#xff01; 想知道自动生成视频的软件有哪些吗&#…

nginx配置白名单服务

http { # 其他配置… # 定义一个名为 whitelist 的共享内存区域 limit_zone whitelist $binary_remote_addr 10m;server {listen 80;server_name example.com;# 白名单配置location / {# 设置只允许特定 IP 访问allow 192.168.1.100; # 允许的 IPallow 192.168.1.10…

【嵌入式学习笔记】---- OLED屏幕工作原理

1 驱动芯片SSD1603简介 1.1 SSD1603芯片图 SSD1603是一款点阵显示屏控制器&#xff0c;可嵌入在屏幕中&#xff0c;用于执行接收数据、显示存储、扫描刷新等任务驱动接口&#xff1a;128个SEG引脚和64个COM引脚&#xff0c;对应 128 64 128\times 64 12864像素点阵显示屏内置…

Gartner发布安全威胁情报产品和服务市场指南:威胁情报产品和服务需具备的8项核心能力和21项可选能力

安全和风险管理领导者很难知道哪些威胁会真正影响到他们的组织。他们应该利用这项研究来选择正确的安全威胁情报产品和服务&#xff0c;并更有效地了解和应对威胁形势。 主要发现 各种规模和垂直行业的企业对威胁情报 (TI) 产品和服务的需求持续增加&#xff0c;但许多组织仍然…

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界!

随着编程语言的不断演进&#xff0c;Python已经成为开发者们心目中的“瑞士军刀”。它的简洁易用、强大的库支持、广泛的应用领域&#xff0c;让它在人工智能、数据分析、网络爬虫、自动化办公等领域展现了无与伦比的优势。那么&#xff0c;如何深入掌握Python这门语言并用它解…

电脑技巧:如何在Win11电脑上调整设置,让屏幕更加护眼?

目录 一、调整屏幕亮度 二、启用夜间模式 三、调整色彩设置 四、使用第三方护眼软件 五、保持良好的用眼习惯 总结 随着长时间使用电脑的人越来越多,护眼问题也变得越来越重要。Win11作为更新的操作系统,提供了更多的设置选项来帮助我们保护眼睛。本文将详细介绍如何在…

宝贝甜梦秘籍!康姿百德柔压磁性枕豪华款守护成长每一夜

科学护航童年梦&#xff01;康姿百德豪华柔压磁性枕&#xff0c;给孩子五星级的睡眠享受 孩子的成长过程中&#xff0c;良好的睡眠环境至关重要。而康姿百德柔压磁性枕&#xff08;豪华款&#xff09;&#xff0c;凭借其独特的设计和材料&#xff0c;成为了孩子成长过程中不可…