netlib:TeamTalk Netlib详解 2024-04-17 11:18:19 0 0 1.简介 主要用于处理tcp连接,自己实现了一个网络库 2.类与接口 2.1 CBaseSocket:socket基础类,封装了常用网络api void CBaseSocket::_SetReuseAddr(SOCKET fd): SO_REUSEADDR复用地址 void CBaseSocket::_SetNonblock(SOCKET fd): O_NONBLOCK设置非阻塞 void CBaseSocket::_SetAddr(const char* ip, const uint16_t port, sockaddr_in* pAddr): 创建sockaddr_in,内部调用gethostbyname支持域名 voidAddBaseSocket(CBaseSocket* pSocket): 插入到g_socket_map,通过全局map建立每一个socket fd和CBaseSocket的对应关系 int CBaseSocket::Listen(const char* server_ip, uint16_t port, callback_t callback, void* callback_data): 设置OnRead回调函数m_callback,创建socket、bind、listen 并设置m_state为SOCKET_STATE_LISTENING; 同时调用 AddBaseSocket(this)将listen socket加入g_socket_map; 调用CEventDispatch::Instance()->AddEvent(m_socket, SOCKET_READ | SOCKET_EXCEP)添加socket可读事件(epoll)。 void CBaseSocket::_AcceptNewSocket(): accept,设置新连接状态(SOCKET_STATE_CONNECTED)属性(NoDelay NoBlock)并将新连接存入g_socket_map void CBaseSocket::OnRead(): 处理epoll可读事件,m_state为SOCKET_STATE_LISTENING时调用_AcceptNewSocket,其他状态是调用m_callback,m_callback在 listen时通过callback设置了回调函数 net_handle_t CBaseSocket::Connect(const char* server_ip, uint16_t port, callback_t callback, void* callback_data): 设置OnWrite回调函数m_callback,连接服务器,创建socket,connect,设置状态为SOCKET_STATE_CONNECTING,将当前CBaseSocket(this)加入g_socket_map void CBaseSocket::OnWrite(): 处理epoll可写事件,m_callback在Connect时通过callback设置了回调函数 2.2 CEventDispatch:socket事件基础类 void CEventDispatch::AddEvent(SOCKET fd, uint8_t socket_event): EPOLL_CTL_ADD添加epoll事件 void CEventDispatch::StartDispatch(uint32_t wait_timeout): while(running)处理epoll io事件,通过类似于Reactor模型的方法,调用FindBaseSocket从g_socket_map中找到socket fd对应的CBaseSocket来触发相应事件处理回调函数(OnRead OnWrite OnClose等),running用于控制该消息泵的持续和退出; void CEventDispatch::StopDispatch(): 将running置为false终止StartDispatch内部的while循环。 定时loop//定时任务基本单元结构typedef struct {callback_tcallback; //定时器回调函数void*user_data; //定时器回调参数uint64_tinterval; //定时器周期uint64_tnext_tick; //下次触发时刻} TimerItem;//使用链表保存所有定时任务list<TimerItem*>m_timer_list; //函数指针,指向任务处理函数,msg表示消息类型typedef void (*callback_t)(void* callback_data, uint8_t msg, uint32_t handle, void* pParam);//向定时任务loop里添加定时任务//若链表里已存在该任务则更新定时周期和下一个触发时刻,若不存在则使用TimerItem封装任务,加入链表中void CEventDispatch::AddTimer(callback_t callback, void* user_data, uint64_t interval);//从m_timer_list里删除定时任务void CEventDispatch::RemoveTimer(callback_t callback, void* user_data)//处理m_timer_list里定时任务//遍历m_timer_list,若当前时刻大于下次触发时刻则执行任务并更新下一触发时刻//StartDispatch函数是一个while(true)会不断执行_CheckTimer,保证定时任务的执行void CEventDispatch::_CheckTimer()优点:StartDispatch里利用epoll_wait(m_epfd, events, 1024, wait_timeout),不会长时间阻塞在这里而占用过多cpu资源缺点:定时器周期受限于wait_timeout,适合处理周期比wait_timeout大的定时任务 任务Loop//使用链表存储loop待执行的任务,复用了TimerItemlist<TimerItem*>m_loop_list;//添加任务到m_loop_listvoid CEventDispatch::AddLoop(callback_t callback, void* user_data);//遍历执行m_loop_list里的任务//StartDispatch函数是一个while(true)会不断执行_CheckLoop,保证任务的执行。void _CheckLoop(); 2.3 NetLib网络库: 通过new CBaseSocket()或FindBaseSocket(handle)使用CBaseSocket内部接口 intnetlib_listen(const char* server_ip, uint16_t port, callback_t callback, void* callback_data): new CBaseSocket,再调用BaseSocket的Listen接口,同时设置OnRead的回调函数; OnRead里m_callback(m_callback_data, NETLIB_MSG_READ, (net_handle_t)m_socket, NULL)调用的就是netlish设置的回调函数。 net_handle_tnetlib_connect(const char* server_ip,uint16_t port,callback_t callback,void* callback_data); new CBaseSocket,再调用BaseSocket的Connect接口 voidnetlib_eventloop(uint32_t wait_timeout): 调用CEventDispatch内部StartDispatch接口 intnetlib_option(net_handle_t handle, int opt, void* optval): 根据opt(NETLIB_OPT_SET_CALLBACK NETLIB_OPT_SET_CALLBACK_DATA…)进行重置回调函数,回调函数参数,读写缓冲区大小,获取ip,port等操作; 如建立新连接时重置OnRead回调函数为imconn_callback并获取对端ip port: netlib_option(handle, NETLIB_OPT_SET_CALLBACK, (void*)imconn_callback) netlib_option(handle, NETLIB_OPT_GET_REMOTE_IP, (void*)&peer_ip) netlib_option(handle, NETLIB_OPT_GET_REMOTE_PORT, (void*)&peer_port) intnetlib_recv(net_handle_t handle, void* buf, int len): 调用FindBaseSocket从g_socket_map找到相应socket,调用Recv接收数据。 intnetlib_send(net_handle_t handle, void* buf, int len): 调用FindBaseSocket从g_socket_map找到相应socket,调用Send发送数据。 intnetlib_close(net_handle_t handle): 调用FindBaseSocket从g_socket_map找到相应socket,调用Close关闭连接。 intnetlib_register_timer(callback_t callback, void* user_data, uint64_t interval): 调用 CEventDispatch::AddTimer添加定时任务 intnetlib_delete_timer(callback_t callback, void* user_data) 调用CEventDispatch::RemoveTimer删除定时任务 intnetlib_add_loop(callback_t callback, void* user_data) 调用 CEventDispatch::AddLoop添加任务 voidnetlib_stop_event() 调用 CEventDispatch::StopDispatch停止消息泵 3.源码链接:TeamTalk_BlueBling测试demo: tests/test_netlib.cpp 4.test_netlib说明测试用例模拟login server,teamtalk客户端登录时会先连接login server获取msg_server的情况再连接msg_server,由于没有模拟msg_server, teamtalk客户端第一阶段获取msg_server的情况会成功,第二阶段连接msg_server会出错,但测试效果(能正常连接收发数据)达到了;teamtalk客户端代码void DoLoginServerHttpOperation::processOpertion()用于第一阶段连接login server获取msg server信息;void LoginOperation::processOpertion()用于第二阶段连接msg server这才是真正的连接。效果图 收藏(0)