TeamTalk--登陆服务器的分析
来源:互联网 发布:mac页面搜索快捷键 编辑:程序博客网 时间:2024/06/06 06:47
登陆服务器启动会执行如下语句:
1 main函数介绍
int main(intargc, char* argv[])
{
CStrExplode client_listen_ip_list(client_listen_ip,';');
for (uint32_ti = 0; i < client_listen_ip_list.GetItemCnt(); i++) {
ret = netlib_listen(client_listen_ip_list.GetItem(i),client_port, client_callback,NULL);
if (ret ==NETLIB_ERROR)
return ret;
}
CStrExplode msg_server_listen_ip_list(msg_server_listen_ip,';');
for (uint32_ti = 0; i < msg_server_listen_ip_list.GetItemCnt();i++) {
ret = netlib_listen(msg_server_listen_ip_list.GetItem(i),msg_server_port, msg_serv_callback,NULL);
if (ret ==NETLIB_ERROR)
return ret;
}
printf("server start listen on:\nFor client %s:%d\nFor MsgServer: %s:%d\n",
client_listen_ip,client_port, msg_server_listen_ip,msg_server_port);
init_login_conn();//实际上是定时轮训login_conn_timer_callback函数,做心跳检测用。
printf("now enter the event loop...\n");
netlib_eventloop(); //开始进入轮训。
return 0;
}
对于客户端的连接会进入client_callback回调,如下:
void client_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam)
{
if (msg ==NETLIB_MSG_CONNECT)
{
CLoginConn* pConn = new CLoginConn();
pConn->OnConnect2(handle,LOGIN_CONN_TYPE_CLIENT);
}
else
{
log("!!!error msg: %d\n",msg);
}
}
可以看到,直接进入CLoginConn::OnConnect2函数,如下:
void CLoginConn::OnConnect2(net_handle_thandle, int conn_type)
{
m_handle = handle;
m_conn_type = conn_type;
ConnMap_t* conn_map = &g_msg_serv_conn_map;
if (conn_type ==LOGIN_CONN_TYPE_CLIENT) {
conn_map = &g_client_conn_map;
}
conn_map->insert(make_pair(handle,this));
netlib_option(handle,NETLIB_OPT_SET_CALLBACK, (void*)imconn_callback);
netlib_option(handle,NETLIB_OPT_SET_CALLBACK_DATA, (void*)conn_map);
}
可以看到,把客户加到g_client_conn_map,handle为accept后的SOCKET,并给SOCKET设置了回调函数imconn_callback,回调参数conn_map。
2 CLoginConn介绍
void CLoginConn::Close()
{
if (m_handle !=NETLIB_INVALID_HANDLE) {
netlib_close(m_handle);
if (m_conn_type ==LOGIN_CONN_TYPE_CLIENT) {
g_client_conn_map.erase(m_handle);
//对于客户端,从g_client_conn_map去掉指定的m_handle即可。
} else {
//对于消息服务器,从g_msg_serv_conn_map去掉指定的m_handle,并从g_msg_serv_info删除消息服务器的信息,并更新总的用户数g_total_online_user_cnt。
g_msg_serv_conn_map.erase(m_handle);
// remove all user count from this message server
map<uint32_t,msg_serv_info_t*>::iteratorit = g_msg_serv_info.find(m_handle);
if (it !=g_msg_serv_info.end()) {
msg_serv_info_t*pMsgServInfo = it->second;
g_total_online_user_cnt -=pMsgServInfo->cur_conn_cnt;
log("onclose from MsgServer: %s:%u\n",pMsgServInfo->hostname.c_str(),pMsgServInfo->port);
delete pMsgServInfo;
g_msg_serv_info.erase(it);
}
}
}
ReleaseRef();
}
void CLoginConn::_HandleMsgServInfo(CImPduMsgServInfo*pPdu)
{
//处理消息服务器的登陆,将服务器信息加入g_msg_serv_info,并更新总的用户数g_total_online_user_cnt。
msg_serv_info_t* pMsgServInfo = new msg_serv_info_t;
pMsgServInfo->ip_addr1 =string(pPdu->GetIp1Addr(),pPdu->GetIp1Len());
pMsgServInfo->ip_addr2 =string(pPdu->GetIp2Addr(),pPdu->GetIp2Len());
pMsgServInfo->port =pPdu->GetPort();
pMsgServInfo->max_conn_cnt =pPdu->GetMaxConnCnt();
pMsgServInfo->cur_conn_cnt =pPdu->GetCurConnCnt();
pMsgServInfo->hostname =string(pPdu->GetHostname(),pPdu->GetHostnameLen());
pMsgServInfo->server_type =pPdu->GetServerType();
g_msg_serv_info.insert(make_pair(m_handle,pMsgServInfo));
g_total_online_user_cnt +=pMsgServInfo->cur_conn_cnt;
log("MsgServInfo, ip_addr1=%s, ip_addr2=%s, port=%d, max_conn_cnt=%d, cur_conn_cnt=%d, "\
"hostname: %s, server_type: %d\n",
pMsgServInfo->ip_addr1.c_str(),pMsgServInfo->ip_addr2.c_str(),pMsgServInfo->port,pMsgServInfo->max_conn_cnt,
pMsgServInfo->cur_conn_cnt,pMsgServInfo->hostname.c_str(),pMsgServInfo->server_type);
}
void CLoginConn::_HandleUserCntUpdate(CImPduUserCntUpdate*pPdu)
{
//处理用户数更新
map<uint32_t,msg_serv_info_t*>::iteratorit = g_msg_serv_info.find(m_handle);
if (it !=g_msg_serv_info.end()) {
//先根据m_handle找到消息服务器的指针。
msg_serv_info_t* pMsgServInfo = it->second;
uint32_t action = pPdu->GetUserAction();
uint32_t user_id = pPdu->GetUserId();
if (action ==USER_CNT_INC) {
//用户数增加的情况
pMsgServInfo->cur_conn_cnt++; //先更服务器信息的当前连接数。
UserConnCntMap_t::iteratoriter = g_user_conn_cnt_map.find(user_id);
//如果user_id未添加过,先添加,再更新总在线数g_total_online_user_cnt;如果user_id已添加过,更新user_id对于的个数。
if(iter ==g_user_conn_cnt_map.end()) {
g_user_conn_cnt_map.insert(make_pair(user_id, 1));
g_total_online_user_cnt++;
} else {
++iter->second;
}
iter = pMsgServInfo->user_cnt_map.find(user_id);
if (iter ==pMsgServInfo->user_cnt_map.end()) {
pMsgServInfo->user_cnt_map.insert(make_pair(user_id, 1));
pMsgServInfo->cur_user_cnt++;
}
else
{
++iter->second;
}
}
else
{
//用户数减少的情况
pMsgServInfo->cur_conn_cnt--; //先更服务器信息的当前连接数。
UserConnCntMap_t::iteratoriter = g_user_conn_cnt_map.find(user_id);
//查找全局用户信息g_user_conn_cnt_map,更新user_id对于的个数,如果为0,更新g_total_online_user_cnt。
if((iter ==g_user_conn_cnt_map.end())) {
log("user_id is not exist, id=%u\n",user_id);
}
else
{
if(--iter->second <= 0)
{
g_user_conn_cnt_map.erase(iter);
--g_total_online_user_cnt;
}
}
//查找服务器信息用户信息user_cnt_map,更新user_id对于的个数,如果为0,更新对应的cur_user_cnt。
iter = pMsgServInfo->user_cnt_map.find(user_id);
if (iter ==pMsgServInfo->user_cnt_map.end())
{
log("no user_id in MsgServer\n");
}
else
{
if (--iter->second <= 0)
{
pMsgServInfo->cur_user_cnt--;
pMsgServInfo->user_cnt_map.erase(iter);
}
}
}
log("%s:%d, conn_cnt=%u, user_cnt=%u, total_cnt=%u\n",pMsgServInfo->hostname.c_str(),
pMsgServInfo->port,pMsgServInfo->cur_conn_cnt,pMsgServInfo->cur_user_cnt,
g_total_online_user_cnt);
}
}
void CLoginConn::_HandleMsgServRequest(CImPduMsgServRequest*pPdu)
{
log("HandleMsgServReq\n");
// no MessageServer available
if (g_msg_serv_info.size() == 0) {
CImPduMsgServResponsepdu(REFUSE_REASON_NO_MSG_SERVER);
pdu.SetReserved(pPdu->GetReserved());
SendPdu(&pdu);
Close();
return;
}
// return a message server with minimum concurrent connection count
msg_serv_info_t* pMsgServInfo;
uint32_t min_user_cnt = (uint32_t)-1;
map<uint32_t,msg_serv_info_t*>::iteratorit_min_conn = g_msg_serv_info.end(),it;
for (it =g_msg_serv_info.begin() ;it != g_msg_serv_info.end();it++) {
pMsgServInfo = it->second;
if ( (pMsgServInfo->cur_conn_cnt <pMsgServInfo->max_conn_cnt) &&
(pMsgServInfo->cur_conn_cnt <min_user_cnt) &&
(pMsgServInfo->server_type ==MSG_SERVER_TYPE_TCP) ) {
it_min_conn = it;
min_user_cnt = pMsgServInfo->cur_conn_cnt;
}
}
if (it_min_conn ==g_msg_serv_info.end()) {
log("All TCP MsgServer are full\n");
CImPduMsgServResponsepdu(REFUSE_REASON_MSG_SERVER_FULL);
pdu.SetReserved(pPdu->GetReserved());
SendPdu(&pdu);
} else {
CImPduMsgServResponsepdu(0, it_min_conn->second->ip_addr1.c_str(),
it_min_conn->second->ip_addr2.c_str(),it_min_conn->second->port);
pdu.SetReserved(pPdu->GetReserved());
SendPdu(&pdu);
}
Close(); // after send MsgServResponse, active close the connection
}
void CLoginConn::_HandleUserConnInfo(CImPduUserConnInfo *pPdu)
{
uint32_t user_cnt = pPdu->GetUserCnt();
user_conn_t* user_conn_list = pPdu->GetUserConnList();
map<uint32_t,msg_serv_info_t*>::iteratorit = g_msg_serv_info.find(m_handle);
if (it !=g_msg_serv_info.end()) {
msg_serv_info_t* pMsgServInfo = it->second;
pMsgServInfo->cur_user_cnt =user_cnt;
for (uint32_ti = 0; i < user_cnt; i++) {
pMsgServInfo->user_cnt_map.insert(make_pair(user_conn_list[i].user_id,user_conn_list[i].conn_cnt));
UserConnCntMap_t::iteratorit_user = g_user_conn_cnt_map.find(user_conn_list[i].user_id);
if(it_user ==g_user_conn_cnt_map.end()) {
g_user_conn_cnt_map.insert(make_pair(user_conn_list[i].user_id, 1));
g_total_online_user_cnt++;
} else {
++it_user->second;
}
}
}
log("HandleUserConnInfo, user_cnt=%u, total_user_cnt=%u\n",user_cnt, g_total_online_user_cnt);
}
- TeamTalk--登陆服务器的分析
- TeamTalk服务器的学习1
- TeamTalk--消息服务器的轮训
- TeamTalk服务器
- 最快速的TeamTalk 服务器部署方
- TeamTalk服务器搭建
- CentOS部署TeamTalk服务器
- TeamTalk 服务器--配置
- TeamTalk源码分析(十) —— 开放一个TeamTalk测试服务器地址和几个测试账号
- TeamTalk 分析TTThread
- 【TeamTalk】login_server分析
- 蘑菇街TeamTalk服务端分析
- TeamTalk 服务端分析 一、编译
- TeamTalk 服务端分析 二、配置
- TeamTalk--MsgServer启动流程分析
- TeamTalk源码分析之login_server
- TeamTalk源码分析之msg_server
- TeamTalk源码分析之db_proxy_server
- HTML5 canvas粒子系统打造逼真飘雪特效
- PHP获取当前域名$_SERVER['HTTP_HOST']和$_SERVER['SERVER_NAME']的区别
- 求 Fibonacci数列前n项之和....
- Haproxy介绍及其定位
- YV12 and NV12
- TeamTalk--登陆服务器的分析
- MySql:局域网和权限用户管理
- 游戏原理和机制
- 数据结构预算法(C语言)之图
- 构造Map并对其排序
- atoi C语言的基本用法 code
- Invoke和BeginInvoke的区别
- c语言编写九九乘法表
- v2ex被墙