文章标题

来源:互联网 发布:java特种兵微盘下载 编辑:程序博客网 时间:2024/05/05 22:19

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服务器这种分布式架构设计的思想也是非常值得学习和借鉴的。
原创粉丝点击