TeamTalk--登陆服务器的分析

登陆服务器启动会执行如下语句:

1 main函数介绍

int main(int argc, char* argv[])

{

CStrExplode client_listen_ip_list(client_listen_ip, ';');

     for (uint32_t i = 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_t i = 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_t handle, 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*>::iterator it = 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*>::iterator it = 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::iterator iter = 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::iterator iter = 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) {

         CImPduMsgServResponse pdu(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*>::iterator it_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");

         CImPduMsgServResponse pdu(REFUSE_REASON_MSG_SERVER_FULL);

         pdu.SetReserved(pPdu->GetReserved());

         SendPdu(&pdu);

     } else {

         CImPduMsgServResponse pdu(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*>::iterator it = 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_t i = 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::iterator it_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);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山西茄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值