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);

}

0 0
原创粉丝点击