文章标题

msg_serve的分析

msg的源代码开始就是加载全局的配置文件 初始化全局的list

在事件eventloop之前有一系列的代码:

//连接msg_serve 
    init_msg_conn();

    init_http_conn();

    init_file_serv_conn(file_server_list, file_server_count);

    init_db_serv_conn(db_server_list2, db_server_count2, concurrent_db_conn_cnt);

    init_login_serv_conn(login_server_list, login_server_count, ip_addr1, ip_addr2, listen_port, max_conn_cnt);

    init_route_serv_conn(route_server_list, route_server_count);

    printf("now enter the event loop...\n");

    netlib_eventloop();

这里面有很多的初始化代码,结构都相似,所以我就找几个进行分析,其它的就不分析了

init_file_conn() init_http_conn() init_login_serv_con()的使用

init_file_conn()的使用

void init_file_serv_conn(serv_info_t* server_list, uint32_t server_count)
{
    g_file_server_list = server_list;
    g_file_server_count = server_count;

    serv_init<CFileServConn>(g_file_server_list, g_file_server_count);

    netlib_register_timer(file_server_conn_timer_callback, NULL, 1000);
    s_file_handler = CFileHandler::getInstance();
}

注意里面调用了serv_init()函数,serv_init()代码是一个模板类,它的结构就是:



//serv_init 
template <class T>
void serv_init(serv_info_t* server_list, uint32_t server_count)
{
    for (uint32_t i = 0; i < server_count; i++) {
        T* pConn = new T();
        pConn->Connect(server_list[i].server_ip.c_str(), server_list[i].server_port, i);
        server_list[i].serv_conn = pConn;
        server_list[i].idle_cnt = 0;
        server_list[i].reconnect_cnt = MIN_RECONNECT_CNT / 2;
    }

}

可以看到就是服务器主动连接服务器 file_serve 好的

注意这是一个函数模板,在这里class T 的类型就是 cfileservcon的类型,

那么展开的代码就是

void serv_init(serv_info_t *server_list,uint32_t server_count){
      for(int i=0;i<serve_count;i++){
           cfileservcon pcon=new cfileservcon();
           pcon->connect(sreve_list[i].serve_ip,c_str);

      }
}

所以下载代码跳转到 pcon->connnect()函数上

代码就是:


void CFileServConn::Connect(const char* server_ip, uint16_t server_port, uint32_t idx)
{
    log("Connecting to FileServer %s:%d\n", server_ip, server_port);

    m_serv_idx = idx;
    m_handle = netlib_connect(server_ip, server_port, imconn_callback, (void*)&g_file_server_conn_map);

    if (m_handle != NETLIB_INVALID_HANDLE) {
        g_file_server_conn_map.insert(make_pair(m_handle, this));
    }
}

cfileserveconn::connect就是调用netlib_connect()

g_file_server_conn_map.insert(make_pair(m_handle,this));保存cfileconnserve的对象cfileserveconn::connect()之后就是调用cbasesocket的connect()

之后调用netlib_connect();

net_handle_t netlib_connect(
        const char* server_ip, 
        uint16_t    port, 
        callback_t  callback, 
        void*       callback_data)
{
    CBaseSocket* pSocket = new CBaseSocket();
    if (!pSocket)
        return NETLIB_INVALID_HANDLE;

    net_handle_t handle = pSocket->Connect(server_ip, port, callback, callback_data);
    if (handle == NETLIB_INVALID_HANDLE)
        delete pSocket;
    return handle;
}

可以看到它创建了casesocket对象和调用了psocket->connect()注意里面的回调函数callback

psocket->connect()的实际使用的情况

et_handle_t CBaseSocket::Connect(const char* server_ip, uint16_t port, callback_t callback, void* callback_data)
{
    log("CBaseSocket::Connect, server_ip=%s, port=%d\n", server_ip, port);

    m_remote_ip = server_ip;
    m_remote_port = port;
    m_callback = callback;
    m_callback_data = callback_data;

    m_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (m_socket == INVALID_SOCKET)
    {
        log("socket failed, err_code=%d\n", _GetErrorCode());
        return NETLIB_INVALID_HANDLE;
    }

    _SetNonblock(m_socket);
    _SetNoDelay(m_socket);

    sockaddr_in serv_addr;
    _SetAddr(server_ip, port, &serv_addr);
    int ret = connect(m_socket, (sockaddr*)&serv_addr, sizeof(serv_addr));
    if ( (ret == SOCKET_ERROR) && (!_IsBlock(_GetErrorCode())) )
    {
        log("connect failed, err_code=%d\n", _GetErrorCode());
        closesocket(m_socket);
        return NETLIB_INVALID_HANDLE;
    }

    m_state = SOCKET_STATE_CONNECTING;
    AddBaseSocket(this);
    CEventDispatch::Instance()->AddEvent(m_socket, SOCKET_ALL);

    return (net_handle_t)m_socket;
}

这里将m_socket对象加入事件机制,之后调用event_loop()的时候就开始轮询对应的事件


需要指出的是:连接服务器、接受连接、收取数据解包、发送数据这四个模块是一个完整的网路库必须具有的东西。这篇文章和上一篇文章完整地介绍了这四个模块,而TeamTalk的实现手法也是目前主流网络库的通用做法。如果从事服务器开发,必须熟练掌握这里面的具体每个细节。而teamtalk服务器这种分布式架构设计的思想也是非常值得学习和借鉴的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值