您的位置:首页 > 其它

文章标题

2017-11-03 18:45 351 查看

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服务器这种分布式架构设计的思想也是非常值得学习和借鉴的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: