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

2024-08-31 23:36

本文主要是介绍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,// ...... 暂时省略无关信令
};

获取最近联系会话

流程图

具体代码逻辑

这篇关于TeamTalk消息服务器(群组相关)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125313

相关文章

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

log4j2相关配置说明以及${sys:catalina.home}应用

${sys:catalina.home} 等价于 System.getProperty("catalina.home") 就是Tomcat的根目录:  C:\apache-tomcat-7.0.77 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" /> 2017-08-10

Node Linux相关安装

下载经编译好的文件cd /optwget https://nodejs.org/dist/v10.15.3/node-v10.15.3-linux-x64.tar.gztar -xvf node-v10.15.3-linux-x64.tar.gzln -s /opt/node-v10.15.3-linux-x64/bin/npm /usr/local/bin/ln -s /opt/nod

git ssh key相关

step1、进入.ssh文件夹   (windows下 下载git客户端)   cd ~/.ssh(windows mkdir ~/.ssh) step2、配置name和email git config --global user.name "你的名称"git config --global user.email "你的邮箱" step3、生成key ssh-keygen

zookeeper相关面试题

zk的数据同步原理?zk的集群会出现脑裂的问题吗?zk的watch机制实现原理?zk是如何保证一致性的?zk的快速选举leader原理?zk的典型应用场景zk中一个客户端修改了数据之后,其他客户端能够马上获取到最新的数据吗?zk对事物的支持? 1. zk的数据同步原理? zk的数据同步过程中,通过以下三个参数来选择对应的数据同步方式 peerLastZxid:Learner服务器(Follo

ActiveMQ—消息特性(延迟和定时消息投递)

ActiveMQ消息特性:延迟和定时消息投递(Delay and Schedule Message Delivery) 转自:http://blog.csdn.net/kimmking/article/details/8443872 有时候我们不希望消息马上被broker投递出去,而是想要消息60秒以后发给消费者,或者我们想让消息没隔一定时间投递一次,一共投递指定的次数。。。 类似

速盾:直播 cdn 服务器带宽?

在当今数字化时代,直播已经成为了一种非常流行的娱乐和商业活动形式。为了确保直播的流畅性和高质量,直播平台通常会使用 CDN(Content Delivery Network,内容分发网络)服务器来分发直播流。而 CDN 服务器的带宽则是影响直播质量的一个重要因素。下面我们就来探讨一下速盾视角下的直播 CDN 服务器带宽问题。 一、直播对带宽的需求 高清视频流 直播通常需要传输高清视频