下面我们以pc端登录为例来具体看一个数据包在服务器端各个服务之间走过的流程:
步骤1:login_server初始化侦听socket,设置新连接到来的回调函数。8080端口,该端口是为http服务配置的。
在login_server.cpp main函数中调用:
netlib_listen调用如下:
pSocket->Listen调用:
AddBaseSocket将该socket加入hash_map中。AddEvent设置需要关注的socket上的事件,这里只关注可读和出错事件。
步骤2: 客户端调用connect()函数连接login_server的8080端口。
步骤3:login_server收到连接请求后调用OnRead方法,OnRead()方法里面调用_AcceptNewSocket(),_AcceptNewSocket()接收新连接,创建新的socket,并调用之前初始化阶段netlib_listen设置的回调函数http_callback。
[cpp] view plain copy
- void CBaseSocket::OnRead()
- {
- if (m_state == SOCKET_STATE_LISTENING)
- {
- _AcceptNewSocket();
- }
- else
- {
- u_long avail = 0;
- if ( (ioctlsocket(m_socket, FIONREAD, &avail) == SOCKET_ERROR) || (avail == 0) )
- {
- m_callback(m_callback_data, NETLIB_MSG_CLOSE, (net_handle_t)m_socket, NULL);
- }
- else
- {
- m_callback(m_callback_data, NETLIB_MSG_READ, (net_handle_t)m_socket, NULL);
- }
- }
- }
[cpp] view plain copy
- void CBaseSocket::_AcceptNewSocket()
- {
- SOCKET fd = 0;
- sockaddr_in peer_addr;
- socklen_t addr_len = sizeof(sockaddr_in);
- char ip_str[64];
- while ( (fd = accept(m_socket, (sockaddr*)&peer_addr, &addr_len)) != INVALID_SOCKET )
- {
- CBaseSocket* pSocket = new CBaseSocket();
- uint32_t ip = ntohl(peer_addr.sin_addr.s_addr);
- uint16_t port = ntohs(peer_addr.sin_port);
- snprintf(ip_str, sizeof(ip_str), "%d.%d.%d.%d", ip >> 24, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
- log("AcceptNewSocket, socket=%d from %s:%dn", fd, ip_str, port);
- pSocket->SetSocket(fd);
- pSocket->SetCallback(m_callback);
- pSocket->SetCallbackData(m_callback_data);
- pSocket->SetState(SOCKET_STATE_CONNECTED);
- pSocket->SetRemoteIP(ip_str);
- pSocket->SetRemotePort(port);
- _SetNoDelay(fd);
- _SetNonblock(fd);
- AddBaseSocket(pSocket);
- CEventDispatch::Instance()->AddEvent(fd, SOCKET_READ | SOCKET_EXCEP);
- m_callback(m_callback_data, NETLIB_MSG_CONNECT, (net_handle_t)fd, NULL);
- }
- }
[cpp] view plain copy
- void http_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam)
- {
- if (msg == NETLIB_MSG_CONNECT)
- {
- CHttpConn* pConn = new CHttpConn();
- pConn->OnConnect(handle);
- }
- else
- {
- log("!!!error msg: %d ", msg);
- }
- }
pConn->OnConnect(handle)中设置http数据的回调函数httpconn_callback:
[cpp] view plain copy
- void CHttpConn::OnConnect(net_handle_t handle)
- {
- printf("OnConnect, handle=%dn", handle);
- m_sock_handle = handle;
- m_state = CONN_STATE_CONNECTED;
- g_http_conn_map.insert(make_pair(m_conn_handle, this));
- netlib_option(handle, NETLIB_OPT_SET_CALLBACK, (void*)httpconn_callback);
- netlib_option(handle, NETLIB_OPT_SET_CALLBACK_DATA, reinterpret_cast<void *>(m_conn_handle) );
- netlib_option(handle, NETLIB_OPT_GET_REMOTE_IP, (void*)&m_peer_ip);
- }
httpconn_callback中处理http可读可写出错事件:
[cpp] view plain copy
- void httpconn_callback(void* callback_data, uint8_t msg, uint32_t handle, uint32_t uParam, void* pParam)
- {
- NOTUSED_ARG(uParam);
- NOTUSED_ARG(pParam);
- // convert void* to uint32_t, oops
- uint32_t conn_handle = *((uint32_t*)(&callback_data));
- CHttpConn* pConn = FindHttpConnByHandle(conn_handle);
- if (!pConn) {
- return;
- }
- switch (msg)
- {
- case NETLIB_MSG_READ:
- pConn->OnRead();
- break;
- case NETLIB_MSG_WRITE:
- pConn->OnWrite();
- break;
- case NETLIB_MSG_CLOSE:
- pConn->OnClose();
- break;
- default:
- log("!!!httpconn_callback error msg: %d ", msg);
- break;
- }
- }
步骤4:客户端连接成功以后,发送http请求,方法是get,请求url:http://192.168.226.128:8080/msg_server。(具体网址与你的机器配置的网址有关)
步骤5:login_server检测到该socket可读,调用pConn->OnRead()方法。
[cpp] view plain copy
- void CHttpConn::OnRead()
- {
- for (;;)
- {
- uint32_t free_buf_len = m_in_buf.GetAllocSize() - m_in_buf.GetWriteOffset();
- if (free_buf_len < READ_BUF_SIZE 1)
- m_in_buf.Extend(READ_BUF_SIZE 1);
- int ret = netlib_recv(m_sock_handle, m_in_buf.GetBuffer() m_in_buf.GetWriteOffset(), READ_BUF_SIZE);
- if (ret <= 0)
- break;
- m_in_buf.IncWriteOffset(ret);
- m_last_recv_tick = get_tick_count();
- }
- // 每次请求对应一个HTTP连接,所以读完数据后,不用在同一个连接里面准备读取下个请求
- char* in_buf = (char*)m_in_buf.GetBuffer();
- uint32_t buf_len = m_in_buf.GetWriteOffset();
- in_buf[buf_len] = '