├── .gitignore ├── BaseSocket.cpp ├── BaseSocket.h ├── CMakeLists.txt ├── EventDispatch.cpp ├── EventDispatch.h ├── Lock.cpp ├── Lock.h ├── Makefile ├── Netlib.cpp ├── Netlib.h ├── Netlib_Test.cpp ├── Ostype.h ├── README.md ├── Util.cpp ├── Util.h ├── build.sh └── netlib /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /BaseSocket.cpp: -------------------------------------------------------------------------------- 1 | #include "BaseSocket.h" 2 | #include "EventDispatch.h" 3 | 4 | typedef hash_map SocketMap; 5 | SocketMap g_socket_map; 6 | 7 | void AddBaseSocket(CBaseSocket* pSocket) 8 | { 9 | g_socket_map.insert(make_pair((net_handle_t)pSocket->GetSocket(), pSocket)); 10 | } 11 | 12 | void RemoveBaseSocket(CBaseSocket* pSocket) 13 | { 14 | g_socket_map.erase((net_handle_t)pSocket->GetSocket()); 15 | } 16 | 17 | CBaseSocket* FindBaseSocket(net_handle_t fd) 18 | { 19 | CBaseSocket* pSocket = NULL; 20 | SocketMap::iterator iter = g_socket_map.find(fd); 21 | if(iter != g_socket_map.end()) 22 | { 23 | pSocket = iter->second; 24 | pSocket->AddRef(); 25 | } 26 | 27 | return pSocket; 28 | } 29 | 30 | CBaseSocket::CBaseSocket() 31 | { 32 | m_socket = INVALID_SOCKET; 33 | m_state = SOCKET_STATE_IDLE; 34 | } 35 | 36 | CBaseSocket::~CBaseSocket() 37 | { 38 | 39 | } 40 | 41 | int CBaseSocket::Listen(const char* server_ip,uint16_t port, callback_t callback, void* callback_data) 42 | { 43 | m_local_ip = server_ip; 44 | m_local_port = port; 45 | m_callback = callback; 46 | m_callback_data = callback_data; 47 | 48 | m_socket = socket(AF_INET, SOCK_STREAM,0); 49 | if(m_socket == INVALID_SOCKET) 50 | { 51 | printf("socket failed , err_code = %d\n",_GetErrorCode()); 52 | return NETLIB_ERROR; 53 | } 54 | 55 | _SetReuseAddr(m_socket); 56 | _SetNonblock(m_socket); 57 | 58 | sockaddr_in serv_addr; 59 | _SetAddr(server_ip, port, &serv_addr); 60 | int ret = ::bind(m_socket, (sockaddr*)&serv_addr, sizeof(serv_addr)); 61 | if( ret == SOCKET_ERROR) 62 | { 63 | // log("bind failed, err_code=%d", _GetErrorCode()); 64 | closesocket(m_socket); 65 | return NETLIB_ERROR; 66 | } 67 | 68 | ret = listen(m_socket, 64); 69 | if( ret == SOCKET_ERROR) 70 | { 71 | // log("listen failed, err_code =%d", _GetErrorCode()); 72 | closesocket(m_socket); 73 | return NETLIB_ERROR; 74 | } 75 | 76 | m_state = SOCKET_STATE_LISTENING; 77 | 78 | // log("CBaseSocket::Listen on %s:%d",server_ip,port); 79 | 80 | AddBaseSocket(this); 81 | CEventDispatch::Instance()->AddEvent(m_socket, SOCKET_READ| SOCKET_EXCEP); 82 | return NETLIB_OK; 83 | } 84 | 85 | net_handle_t CBaseSocket::Connect(const char* server_ip,uint16_t port, callback_t callback,void *callback_data) 86 | { 87 | //log("CBaseSocket::Connect, server_ip=%s,port=%d", server_ip, port); 88 | 89 | m_remote_ip = server_ip; 90 | m_remote_port = port; 91 | m_callback = callback; 92 | m_callback_data = callback_data; 93 | 94 | m_socket = socket(AF_INET, SOCK_STREAM, 0); 95 | if( m_socket == INVALID_SOCKET) 96 | { 97 | // log("socket failed, err_code=%d", _GetErrorCode()); 98 | return NETLIB_INVALID_HANDLE; 99 | } 100 | 101 | _SetNonblock(m_socket); 102 | _SetNoDelay(m_socket); 103 | 104 | sockaddr_in serv_addr; 105 | _SetAddr(server_ip, port, &serv_addr); 106 | int ret = connect(m_socket, (sockaddr*)&serv_addr,sizeof(serv_addr)); 107 | if((ret == SOCKET_ERROR) && (!_IsBlock(_GetErrorCode()))) 108 | { 109 | // log("connect failed,err_code=%d",_GetErrorCode()); 110 | closesocket(m_socket); 111 | return NETLIB_INVALID_HANDLE; 112 | } 113 | 114 | m_state = SOCKET_STATE_CONNECTING; 115 | AddBaseSocket(this); 116 | CEventDispatch::Instance()->AddEvent(m_socket, SOCKET_ALL); 117 | 118 | return (net_handle_t)m_socket; 119 | } 120 | 121 | int CBaseSocket::Send(void* buf, int len) 122 | { 123 | if( m_state != SOCKET_STATE_CONNECTED) 124 | return NETLIB_ERROR; 125 | 126 | int ret = send(m_socket, (char*)buf, len, 0); 127 | if( ret == SOCKET_ERROR) 128 | { 129 | int err_code = _GetErrorCode(); 130 | if(_IsBlock(err_code)) 131 | { 132 | #if ((defined _WIN32)|| (defined __APPLE__)) 133 | CEventDispatch::Instance()->AddEvent(m_socket, SOCKET_WRITE); 134 | #endif 135 | ret = 0; 136 | } 137 | else 138 | { 139 | // log("!!!send failed, error code:%d",err_code); 140 | } 141 | } 142 | 143 | return ret; 144 | } 145 | 146 | int CBaseSocket::Recv(void* buf, int len) 147 | { 148 | return recv(m_socket, (char*)buf, len ,0); 149 | } 150 | 151 | int CBaseSocket::Close() 152 | { 153 | CEventDispatch::Instance()->RemoveEvent(m_socket, SOCKET_ALL); 154 | RemoveBaseSocket(this); 155 | closesocket(m_socket); 156 | ReleaseRef(); 157 | 158 | return 0; 159 | } 160 | 161 | void CBaseSocket::OnRead() 162 | { 163 | if( m_state == SOCKET_STATE_LISTENING) 164 | { 165 | _AcceptNewSocket(); 166 | } 167 | else 168 | { 169 | u_long avail = 0; 170 | if((ioctlsocket(m_socket, FIONREAD,&avail) == SOCKET_ERROR) || (avail == 0)) 171 | { 172 | m_callback(m_callback_data, NETLIB_MSG_CLOSE, (net_handle_t)m_socket, NULL); 173 | } 174 | else 175 | { 176 | m_callback(m_callback_data, NETLIB_MSG_READ, (net_handle_t)m_socket, NULL); 177 | } 178 | } 179 | } 180 | 181 | void CBaseSocket::OnWrite() 182 | { 183 | #if ((defined _WIN32) || (defined __APPLE__)) 184 | CEventDispatch::Instance()->RemoveEvent(m_socket, SOCKET_WRITE); 185 | #endif 186 | 187 | if(m_state == SOCKET_STATE_CONNECTING) 188 | { 189 | int error = 0; 190 | socklen_t len = sizeof(error); 191 | #ifndef _WIN32 192 | 193 | getsockopt(m_socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len); 194 | #else 195 | getsockopt(m_socket, SOL_SOCKET, SO_ERROR, (void*)&error,&len); 196 | #endif 197 | if(error) 198 | { 199 | m_callback(m_callback_data, NETLIB_MSG_CLOSE, (net_handle_t)m_socket,NULL); 200 | } 201 | else 202 | { 203 | m_state = SOCKET_STATE_CONNECTED; 204 | m_callback(m_callback_data, NETLIB_MSG_CONFIRM,(net_handle_t)m_socket,NULL); 205 | } 206 | } 207 | else 208 | { 209 | m_callback(m_callback_data, NETLIB_MSG_WRITE, (net_handle_t)m_socket, NULL); 210 | } 211 | } 212 | 213 | void CBaseSocket::OnClose() 214 | { 215 | m_state = SOCKET_STATE_CLOSING; 216 | m_callback(m_callback_data,NETLIB_MSG_CLOSE, (net_handle_t)m_socket, NULL); 217 | } 218 | 219 | 220 | void CBaseSocket::SetSendBufSize(uint32_t send_size) 221 | { 222 | int ret = setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, &send_size, 4); 223 | if(ret == SOCKET_ERROR) 224 | { 225 | //log("set SO_SNDBUF failed for fd=%d", m_socket); 226 | } 227 | 228 | socklen_t len =4; 229 | int size = 0; 230 | getsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, &size,&len); 231 | //log("socket=%d send_buf_size=%d", m_socket, size); 232 | } 233 | 234 | void CBaseSocket::SetRecvBufSize(uint32_t recv_size) 235 | { 236 | int ret = setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, &recv_size, 4); 237 | if( ret == SOCKET_ERROR) 238 | { 239 | // log("set SO_RCVBUF failed for fd=%d", m_socket); 240 | } 241 | 242 | socklen_t len = 4; 243 | int size = 0; 244 | getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF,&size, &len); 245 | //log("socket=%d recv_buf_size=%d", m_socket, size); 246 | } 247 | 248 | int CBaseSocket::_GetErrorCode() 249 | { 250 | #ifdef _WIN32 251 | return wSAGetLastError(); 252 | #else 253 | return errno; 254 | #endif 255 | } 256 | 257 | bool CBaseSocket::_IsBlock(int error_code) 258 | { 259 | #ifdef _WIN32 260 | return ((error_code == WSAEINPROGRESS) || (error_code == WSAEWOULDBLOCK)); 261 | #else 262 | return ((error_code == EINPROGRESS) || (error_code == EWOULDBLOCK)); 263 | #endif 264 | } 265 | 266 | void CBaseSocket::_SetNonblock(SOCKET fd) 267 | { 268 | #ifdef _WIN32 269 | u_long nonblock = 1; 270 | int ret = ioctlsocket(fd, FIONBIO,&nonblock); 271 | #else 272 | int ret = fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL)); 273 | #endif 274 | if(ret == SOCKET_ERROR) 275 | { 276 | //log("_SetNonblock failed, err_code=%d", _GetErrorCode()); 277 | } 278 | } 279 | 280 | void CBaseSocket::_SetReuseAddr(SOCKET fd) 281 | { 282 | int reuse = 1; 283 | int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)); 284 | if( ret == SOCKET_ERROR) 285 | { 286 | // log("_SetReuseAddr failed, err_code=%d", _GetErrorCode()); 287 | } 288 | } 289 | 290 | void CBaseSocket::_SetNoDelay(SOCKET fd) 291 | { 292 | int nodelay = 1; 293 | int ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay)); 294 | if( ret == SOCKET_ERROR) 295 | { 296 | // log("_SetNoDelay failed, err_code=%d",_GetErrorCode()); 297 | } 298 | } 299 | 300 | void CBaseSocket::_SetAddr(const char* ip, const uint16_t port, sockaddr_in * pAddr) 301 | { 302 | memset(pAddr, 0, sizeof(sockaddr_in)); 303 | pAddr->sin_family = AF_INET; 304 | pAddr->sin_port = htons(port); 305 | pAddr->sin_addr.s_addr = inet_addr(ip); 306 | if(pAddr->sin_addr.s_addr == INADDR_NONE) 307 | { 308 | hostent* host = gethostbyname(ip); 309 | if( host == NULL) 310 | { 311 | //log("gethostbyname failed, ip=%s",ip); 312 | return; 313 | } 314 | pAddr->sin_addr.s_addr = *(uint32_t*)host->h_addr; 315 | } 316 | } 317 | 318 | void CBaseSocket::_AcceptNewSocket() 319 | { 320 | SOCKET fd = 0; 321 | sockaddr_in peer_addr; 322 | socklen_t addr_len = sizeof(sockaddr_in); 323 | char ip_str[64]; 324 | 325 | while((fd = accept(m_socket, (sockaddr*)&peer_addr, &addr_len))!=INVALID_SOCKET) 326 | { 327 | CBaseSocket* pSocket = new CBaseSocket(); 328 | 329 | uint32_t ip = ntohl(peer_addr.sin_addr.s_addr); 330 | uint16_t port = ntohs(peer_addr.sin_port); 331 | 332 | snprintf(ip_str, sizeof(ip_str), "%d.%d.%d.%d",ip>>24,(ip>>16)&0xFF, (ip>>8)&0xFF, ip &0xFF); 333 | 334 | pSocket->SetSocket(fd); 335 | pSocket->SetCallback(m_callback); 336 | pSocket->SetCallbackData(m_callback_data); 337 | pSocket->SetState(SOCKET_STATE_CONNECTED); 338 | pSocket->SetRemoteIP(ip_str); 339 | pSocket->SetRemotePort(port); 340 | 341 | _SetNoDelay(fd); 342 | _SetNonblock(fd); 343 | AddBaseSocket(pSocket); 344 | CEventDispatch::Instance()->AddEvent(fd, SOCKET_READ| SOCKET_EXCEP); 345 | m_callback(m_callback_data, NETLIB_MSG_CONNECT, (net_handle_t)fd, NULL); 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /BaseSocket.h: -------------------------------------------------------------------------------- 1 | #ifndef __SOCKET_H__ 2 | #define __SOCKET_H__ 3 | 4 | #include 5 | #include "Ostype.h" 6 | #include "Util.h" 7 | 8 | using namespace std; 9 | 10 | enum 11 | { 12 | SOCKET_STATE_IDLE, 13 | SOCKET_STATE_LISTENING, 14 | SOCKET_STATE_CONNECTING, 15 | SOCKET_STATE_CONNECTED, 16 | SOCKET_STATE_CLOSING 17 | }; 18 | 19 | class CBaseSocket:public CRefObject 20 | { 21 | public: 22 | CBaseSocket(); 23 | virtual ~CBaseSocket(); 24 | SOCKET GetSocket() {return m_socket;} 25 | void SetSocket(SOCKET fd) {m_socket = fd;} 26 | void SetState(uint8_t state) { m_state = state;} 27 | 28 | void SetCallback(callback_t callback) { m_callback = callback;} 29 | void SetCallbackData(void* data) { m_callback_data = data;} 30 | void SetRemoteIP(char* ip) { m_remote_ip = ip;} 31 | void SetRemotePort(uint16_t port) {m_remote_port = port;} 32 | void SetSendBufSize(uint32_t send_size); 33 | void SetRecvBufSize(uint32_t recv_size); 34 | 35 | const char* GetRemoteIP() { return m_remote_ip.c_str();} 36 | uint16_t GetRemotePort() { return m_remote_port;} 37 | const char* GetLocalIP() { return m_local_ip.c_str();} 38 | uint16_t GetLocalPort() { return m_local_port;} 39 | 40 | public: 41 | int Listen( 42 | const char* server_ip, 43 | uint16_t port, 44 | callback_t callback, 45 | void* callback_data 46 | ); 47 | 48 | net_handle_t Connect( 49 | const char* server_ip, 50 | uint16_t port, 51 | callback_t callback, 52 | void* callback_data 53 | ); 54 | 55 | int Send(void* buf, int len); 56 | int Recv(void* buf, int len); 57 | int Close(); 58 | 59 | public: 60 | void OnRead(); 61 | void OnWrite(); 62 | void OnClose(); 63 | 64 | private: 65 | int _GetErrorCode(); 66 | bool _IsBlock(int error_code); 67 | 68 | void _SetNonblock(SOCKET fd); 69 | void _SetReuseAddr(SOCKET fd); 70 | void _SetNoDelay(SOCKET fd); 71 | void _SetAddr(const char* ip , const uint16_t port, sockaddr_in *pAddr); 72 | void _AcceptNewSocket(); 73 | 74 | private: 75 | string m_remote_ip; 76 | uint16_t m_remote_port; 77 | string m_local_ip; 78 | uint16_t m_local_port; 79 | 80 | callback_t m_callback; 81 | void* m_callback_data; 82 | 83 | uint8_t m_state; 84 | SOCKET m_socket; 85 | 86 | }; 87 | 88 | CBaseSocket* FindBaseSocket(net_handle_t fd); 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 2 | 3 | set(SOURCE_FILES 4 | Lock.h 5 | Lock.cpp 6 | EventDispatch.h 7 | EventDispatch.cpp 8 | BaseSocket.h 9 | BaseSocket.cpp 10 | Util.h 11 | Util.cpp 12 | Ostype.h 13 | Netlib.h 14 | Netlib.cpp 15 | Netlib_Test.cpp 16 | ) 17 | 18 | add_executable(netlib ${SOURCE_FILES}) 19 | target_link_libraries(netlib pthread) 20 | -------------------------------------------------------------------------------- /EventDispatch.cpp: -------------------------------------------------------------------------------- 1 | #include "EventDispatch.h" 2 | #include "BaseSocket.h" 3 | 4 | #define MIN_TIMER_DURATION 100 //100miliseconds 5 | 6 | CEventDispatch* CEventDispatch::m_pEventDispatch = NULL; 7 | 8 | CEventDispatch::CEventDispatch() 9 | { 10 | running = false; 11 | #ifdef _WIN32 12 | FD_ZERO(&m_read_set); 13 | FD_ZERO(&m_write_set); 14 | FD_ZERO(&m_excep_set); 15 | #elif __APPLE__ 16 | m_kqfd = kqueue(); 17 | if(m_kqfd == -1) 18 | { 19 | // log("kqueue failed"); 20 | } 21 | #else 22 | m_epfd = epoll_create(1024); 23 | if( m_epfd == -1) 24 | { 25 | // log("epoll_create failed"); 26 | } 27 | #endif 28 | } 29 | 30 | 31 | CEventDispatch::~CEventDispatch() 32 | { 33 | #ifdef _WIN32 34 | 35 | #elif __APPLE__ 36 | close(m_kqfd); 37 | #else 38 | close(m_epfd); 39 | #endif 40 | } 41 | 42 | 43 | void CEventDispatch::AddTimer(callback_t callback, void* user_data, uint64_t interval) 44 | { 45 | list::iterator it; 46 | for( it = m_timer_list.begin(); it != m_timer_list.end(); it++) 47 | { 48 | TimerItem* pItem = *it; 49 | if( pItem->callback == callback && pItem->user_data == user_data) 50 | { 51 | pItem->interval = interval; 52 | pItem->next_tick = get_tick_count() + interval; 53 | return; 54 | } 55 | } 56 | 57 | TimerItem* pItem = new TimerItem; 58 | pItem->callback = callback; 59 | pItem->user_data = user_data; 60 | pItem->interval = interval; 61 | pItem->next_tick = get_tick_count() + interval; 62 | m_timer_list.push_back(pItem); 63 | } 64 | 65 | void CEventDispatch::RemoveTimer(callback_t callback, void* user_data) 66 | { 67 | list::iterator it; 68 | for( it = m_timer_list.begin(); it != m_timer_list.end() ; it++) 69 | { 70 | TimerItem* pItem = *it; 71 | if( pItem->callback == callback && pItem->user_data == user_data) 72 | { 73 | m_timer_list.erase(it); 74 | delete pItem; 75 | return; 76 | } 77 | } 78 | } 79 | 80 | void CEventDispatch::_CheckTimer() 81 | { 82 | uint64_t curr_tick = get_tick_count(); 83 | list::iterator it; 84 | 85 | for( it = m_timer_list.begin(); it != m_timer_list.end();) 86 | { 87 | TimerItem* pItem = *it; 88 | it++; 89 | if(curr_tick >= pItem->next_tick) 90 | { 91 | pItem->next_tick += pItem->interval; 92 | pItem->callback(pItem->user_data,NETLIB_MSG_TIMER,0,NULL); 93 | } 94 | } 95 | 96 | } 97 | 98 | 99 | void CEventDispatch::AddLoop(callback_t callback, void* user_data) 100 | { 101 | TimerItem* pItem = new TimerItem; 102 | pItem->callback = callback; 103 | pItem->user_data = user_data; 104 | m_loop_list.push_back(pItem); 105 | } 106 | 107 | void CEventDispatch::_CheckLoop() 108 | { 109 | for(list::iterator it = m_loop_list.begin(); it != m_loop_list.end(); it++) 110 | { 111 | TimerItem* pItem = *it; 112 | pItem->callback(pItem->user_data, NETLIB_MSG_LOOP, 0, NULL); 113 | } 114 | } 115 | 116 | CEventDispatch* CEventDispatch::Instance() 117 | { 118 | if( m_pEventDispatch == NULL) 119 | { 120 | m_pEventDispatch = new CEventDispatch(); 121 | } 122 | 123 | return m_pEventDispatch; 124 | } 125 | 126 | #ifdef _WIN32 127 | 128 | void CEventDispatch::AddEvent(SOCKET fd, uint8_t socket_event) 129 | { 130 | CAutoLock func_lock(&m_lock); 131 | 132 | if((socket_event & SOCKET_READ) != 0) 133 | { 134 | FD_SET(fd, &m_read_set); 135 | } 136 | 137 | if((socket_event & SOCKET_WRITE) != 0) 138 | { 139 | FD_SET(fd, &m_write_set); 140 | } 141 | 142 | if((socket_event & SOCKET_EXCEP) != 0) 143 | { 144 | FD_SET(fd, &m_excep_set); 145 | } 146 | } 147 | 148 | void CEventDispatch::RemoveEvent(SOCKET fd, uint8_t socket_event) 149 | { 150 | CAutoLock func_lock(&m_lock); 151 | 152 | if((socket_event & SOCKET_READ) != 0) 153 | { 154 | FD_CLR(fd, &m_read_set); 155 | } 156 | 157 | if((socket_event & SOCKET_WRITE) != 0) 158 | { 159 | FD_CLR(fd, &m_write_set); 160 | } 161 | 162 | if((socket_event & SOCKET_EXCEP) != 0) 163 | { 164 | FD_CLR(fd, &m_excep_set); 165 | } 166 | } 167 | 168 | void CEventDispatch::StartDispatch(uint32_t wait_timeout) 169 | { 170 | fd_set read_set, write_set, excep_set; 171 | timeval timeout; 172 | timeout.tv_sec = 0; 173 | timeout.tv_usec = wait_timeout * 1000; //10millisecond 174 | 175 | if(running) 176 | return; 177 | running = true; 178 | 179 | while(running) 180 | { 181 | _CheckTimer(); 182 | _CheckLoop(); 183 | 184 | if(!m_read_set.fd_count && !m_write_set.fd_count && !m_excep_set.fd_count) 185 | { 186 | Sleep(MIN_TIMER_DURATION); 187 | continue; 188 | } 189 | 190 | m_lock.lock(); 191 | memcpy(&read_set, &m_read_set, sizeof(fd_set)); 192 | memcpy(&write_set, &m_write_set, sizeof(fd_set)); 193 | memcpy(^excep_set, &m_excep_set, sizeof(fd_set)); 194 | m_lock.unlock(); 195 | 196 | int nfds = select(0, &read_set, &write_set, &excep_set, &timeout); 197 | 198 | if(nfds == SOCKET_ERROR) 199 | { 200 | log("select failed, error code: %d", GetLastError()); 201 | Sleep(MIN_TIMER_DURATION); 202 | continue; 203 | } 204 | 205 | if( nfds == 0) 206 | { 207 | continue; 208 | } 209 | 210 | for(u_int i = 0; i < read_set.fd_count; i++) 211 | { 212 | SOCKET fd = read_set.fd_array[i]; 213 | CBaseSocket* pSocket = FindBaseSocket((net_handle_t)fd); 214 | if(pSocket) 215 | { 216 | pSocket->OnRead(); 217 | pSocket->ReleaseRef(); 218 | } 219 | 220 | } 221 | 222 | for(u_int i = 0; i < write_set.fd_count; i++) 223 | { 224 | SOKET fd = write_set.fd_array[i]; 225 | CBaseSocket* pSocket = FindBaseSocket((net_handle_t)fd); 226 | if(pSocket) 227 | { 228 | pSocket->OnWrite(); 229 | pSocket->ReleaseRef(); 230 | } 231 | 232 | } 233 | 234 | for(u_int = 0; i < excep_set.fd_count; i++) 235 | { 236 | SOCKET fd = excep_set.fd_arrray[i]; 237 | CBaseSocket* pSocket = FindBaseSocket((net_handle_t)fd); 238 | if(pSocket) 239 | { 240 | pSocket->OnClose(); 241 | pSocket->ReleaseRef(); 242 | } 243 | } 244 | } 245 | 246 | } 247 | 248 | void CEventDispatch::StopDispatch() 249 | { 250 | running = false; 251 | } 252 | 253 | #elif __APPLE__ 254 | 255 | void CEventDispatch::AddEvent(SOCKET fd, uint8_t socket_event) 256 | { 257 | struct kevent ke; 258 | 259 | if((socket_event & SOCKET_READ) !=0 ) 260 | { 261 | EV_SET(&ke, fd, EVFILE_READ, EV_ADD, 0, 0, NULL); 262 | kevent(m_kqfd , &ke, 1 , NULL, 0, NULL); 263 | } 264 | 265 | if((socket_event & SOCKET_WRITE) != 0) 266 | { 267 | EV_SET(&ke, fd, EVFILE_WRITE , EV_ADD, 0,0,NULL); 268 | kevent(m_kqfd, &ke, 1, NULL, 0, NULL); 269 | } 270 | } 271 | 272 | void CEventDispatch::RemoveEvent(SOCKET fd, uint8_t socket_event) 273 | { 274 | struct kevent ke; 275 | if((socket_event & SOCKET_READ) != 0) 276 | { 277 | EV_SET(&ke, fd, EVFILE_READ, EV_DELETE, 0, 0, NULL); 278 | kevent(m_kqfd, &ke, 1, NULL, 0, NULL); 279 | } 280 | 281 | if((socket_event & SOCKET_WRITE) != 0) 282 | { 283 | EV_SET(&ke, fd, EVFILE_WRITE, EV_DELETE, 0, 0, NULL); 284 | kevent(m_kqfd, &ke, 1, NULL , 0, NULL); 285 | } 286 | } 287 | 288 | void CEventDispatch::StartDispatch(uint32_t wait_timeout) 289 | { 290 | struct kevent events[1024]; 291 | int nfds = 0; 292 | struct timespec timeout; 293 | timeout.tv_sec = 0; 294 | timeout.tv_nsec = wait_timeout * 1000000; 295 | 296 | if(running) 297 | return; 298 | running = true; 299 | 300 | while(running) 301 | { 302 | nfds = kevent(m_kqfd, NULL, 0, events, 1024, &timeout); 303 | 304 | for(int i = 0; i < nfds; i++) 305 | { 306 | int ev_fd = events[i].ident; 307 | CBaseSocket* pSocket = FindBaseSocket(ev_fd); 308 | if(!pSocket) 309 | continue; 310 | 311 | if(events[i].filter = EVFILT_READ) 312 | { 313 | pSocket->onRead(); 314 | } 315 | 316 | if(events[i].filter == EVFILT_WRITE) 317 | { 318 | pSocket->onWrite(); 319 | } 320 | pSocket->ReleaseRef(); 321 | } 322 | } 323 | } 324 | 325 | void CEventDispatch::StopDispatch() 326 | { 327 | running = false; 328 | } 329 | 330 | #else 331 | 332 | void CEventDispatch::AddEvent(SOCKET fd, uint8_t socket_event) 333 | { 334 | struct epoll_event ev; 335 | ev.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLPRI | EPOLLERR | EPOLLHUP; 336 | ev.data.fd = fd; 337 | if(epoll_ctl(m_epfd, EPOLL_CTL_ADD , fd, &ev) != 0) 338 | { 339 | // log("epoll_ctl() failed, errno=%d", errno); 340 | } 341 | } 342 | 343 | void CEventDispatch::RemoveEvent(SOCKET fd, uint8_t socket_event) 344 | { 345 | if(epoll_ctl(m_epfd, EPOLL_CTL_DEL, fd, NULL) != 0) 346 | { 347 | // log("epoll_ctl failed , errno=%d", errno); 348 | } 349 | } 350 | 351 | void CEventDispatch::StartDispatch(uint32_t wait_timeout) 352 | { 353 | struct epoll_event events[1024]; 354 | int nfds = 0; 355 | 356 | if(running) 357 | return; 358 | 359 | while(running) 360 | { 361 | nfds = epoll_wait(m_epfd, events, 1024, wait_timeout); 362 | for(int i = 0; i < nfds; i++) 363 | { 364 | int ev_fd = events[i].data.fd; 365 | CBaseSocket* pSocket = FindBaseSocket(ev_fd); 366 | if(!pSocket) 367 | continue; 368 | 369 | #ifdef EPOLLRDHUP 370 | if(events[i].events & EPOLLRDHUP) 371 | { 372 | pSocket->OnClose(); 373 | } 374 | #endif 375 | 376 | if(events[i].events & EPOLLIN) 377 | { 378 | pSocket->OnRead(); 379 | } 380 | 381 | if(events[i].events & EPOLLOUT) 382 | { 383 | pSocket->OnWrite(); 384 | } 385 | 386 | if(events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)) 387 | { 388 | pSocket->OnClose(); 389 | } 390 | 391 | } 392 | _CheckTimer(); 393 | _CheckLoop(); 394 | } 395 | } 396 | 397 | void CEventDispatch::StopDispatch() 398 | { 399 | running = false; 400 | } 401 | 402 | #endif 403 | -------------------------------------------------------------------------------- /EventDispatch.h: -------------------------------------------------------------------------------- 1 | #ifndef __EVENT_DISPATCH_H__ 2 | #define __EVENT_DISPATCH_H__ 3 | 4 | #include "Ostype.h" 5 | #include "Util.h" 6 | 7 | #include "Lock.h" 8 | 9 | enum{ 10 | SOCKET_READ = 0x01, 11 | SOCKET_WRITE = 0x02, 12 | SOCKET_EXCEP = 0X04, 13 | SOCKET_ALL = 0x7 14 | }; 15 | 16 | class CEventDispatch 17 | { 18 | public: 19 | virtual ~CEventDispatch(); 20 | void AddEvent(SOCKET fd, uint8_t socket_event); 21 | void RemoveEvent(SOCKET fd, uint8_t socket_event); 22 | 23 | void AddTimer(callback_t callback, void* user_data, uint64_t interval); 24 | void RemoveTimer(callback_t callback, void* user_data); 25 | 26 | void AddLoop(callback_t callback, void* user_data); 27 | void StartDispatch(uint32_t wait_timeout = 100); 28 | void StopDispatch(); 29 | 30 | bool isRunning() {return running;} 31 | 32 | static CEventDispatch* Instance(); 33 | 34 | protected: 35 | CEventDispatch(); 36 | 37 | private: 38 | void _CheckTimer(); 39 | void _CheckLoop(); 40 | 41 | typedef struct{ 42 | callback_t callback; 43 | void* user_data; 44 | uint64_t interval; 45 | uint64_t next_tick; 46 | }TimerItem; 47 | 48 | private: 49 | #ifdef _WIN32 50 | fd_set m_read_set; 51 | fd_set m_write_set; 52 | fd_set m_excep_set; 53 | #elif __APPLE__ 54 | int m_kqfd; 55 | #else 56 | int m_epfd; 57 | #endif 58 | CLock m_lock; 59 | list m_timer_list; 60 | list m_loop_list; 61 | 62 | static CEventDispatch* m_pEventDispatch; 63 | 64 | bool running; 65 | 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Lock.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharmingZhou/netlib/77697207d0b7a0db23599c1a4f603d40b35b2084/Lock.cpp -------------------------------------------------------------------------------- /Lock.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOCK_H__ 2 | #define __LOCK_H__ 3 | 4 | #include "Ostype.h" 5 | 6 | class CLock 7 | { 8 | public: 9 | CLock(); 10 | virtual ~CLock(); 11 | void lock(); 12 | void unlock(); 13 | pthread_mutex_t& getMutex() { return m_lock; } 14 | #ifndef _WIN32 15 | virtual bool try_lock(); 16 | #endif 17 | private: 18 | #ifdef _WIN32 19 | CRITICAL_SECTION m_critical_section; 20 | #else 21 | pthread_mutex_t m_lock; 22 | #endif 23 | }; 24 | 25 | #ifndef _WIN32 26 | class CRWLock 27 | { 28 | public: 29 | CRWLock(); 30 | virtual ~CRWLock(); 31 | void rlock(); 32 | void wlock(); 33 | void unlock(); 34 | bool try_rlock(); 35 | bool try_wlock(); 36 | private: 37 | pthread_rwlock_t m_lock; 38 | }; 39 | 40 | class CAutoRWLock 41 | { 42 | public: 43 | CAutoRWLock(CRWLock* pLock, bool bRLock = true); 44 | virtual ~CAutoRWLock(); 45 | private: 46 | CRWLock* m_pLock; 47 | }; 48 | 49 | #endif 50 | 51 | class CAutoLock 52 | { 53 | public: 54 | CAutoLock(CLock* pLock); 55 | virtual ~CAutoLock(); 56 | private: 57 | CLock* m_pLock; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 2.8 3 | 4 | # Default target executed when no arguments are given to make. 5 | default_target: all 6 | .PHONY : default_target 7 | 8 | #============================================================================= 9 | # Special targets provided by cmake. 10 | 11 | # Disable implicit rules so canonical targets will work. 12 | .SUFFIXES: 13 | 14 | # Remove some rules from gmake that .SUFFIXES does not remove. 15 | SUFFIXES = 16 | 17 | .SUFFIXES: .hpux_make_needs_suffix_list 18 | 19 | # Suppress display of executed commands. 20 | $(VERBOSE).SILENT: 21 | 22 | # A target that is always out of date. 23 | cmake_force: 24 | .PHONY : cmake_force 25 | 26 | #============================================================================= 27 | # Set environment variables for the build. 28 | 29 | # The shell in which to execute make rules. 30 | SHELL = /bin/sh 31 | 32 | # The CMake executable. 33 | CMAKE_COMMAND = /usr/bin/cmake 34 | 35 | # The command to remove a file. 36 | RM = /usr/bin/cmake -E remove -f 37 | 38 | # Escaping for special characters. 39 | EQUALS = = 40 | 41 | # The program to use to edit the cache. 42 | CMAKE_EDIT_COMMAND = /usr/bin/ccmake 43 | 44 | # The top-level source directory on which CMake was run. 45 | CMAKE_SOURCE_DIR = /root/netlib 46 | 47 | # The top-level build directory on which CMake was run. 48 | CMAKE_BINARY_DIR = /root/netlib 49 | 50 | #============================================================================= 51 | # Targets provided globally by CMake. 52 | 53 | # Special rule for the target edit_cache 54 | edit_cache: 55 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." 56 | /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) 57 | .PHONY : edit_cache 58 | 59 | # Special rule for the target edit_cache 60 | edit_cache/fast: edit_cache 61 | .PHONY : edit_cache/fast 62 | 63 | # Special rule for the target rebuild_cache 64 | rebuild_cache: 65 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." 66 | /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) 67 | .PHONY : rebuild_cache 68 | 69 | # Special rule for the target rebuild_cache 70 | rebuild_cache/fast: rebuild_cache 71 | .PHONY : rebuild_cache/fast 72 | 73 | # The main all target 74 | all: cmake_check_build_system 75 | $(CMAKE_COMMAND) -E cmake_progress_start /root/netlib/CMakeFiles /root/netlib/CMakeFiles/progress.marks 76 | $(MAKE) -f CMakeFiles/Makefile2 all 77 | $(CMAKE_COMMAND) -E cmake_progress_start /root/netlib/CMakeFiles 0 78 | .PHONY : all 79 | 80 | # The main clean target 81 | clean: 82 | $(MAKE) -f CMakeFiles/Makefile2 clean 83 | .PHONY : clean 84 | 85 | # The main clean target 86 | clean/fast: clean 87 | .PHONY : clean/fast 88 | 89 | # Prepare targets for installation. 90 | preinstall: all 91 | $(MAKE) -f CMakeFiles/Makefile2 preinstall 92 | .PHONY : preinstall 93 | 94 | # Prepare targets for installation. 95 | preinstall/fast: 96 | $(MAKE) -f CMakeFiles/Makefile2 preinstall 97 | .PHONY : preinstall/fast 98 | 99 | # clear depends 100 | depend: 101 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 102 | .PHONY : depend 103 | 104 | #============================================================================= 105 | # Target rules for targets named netlib 106 | 107 | # Build rule for target. 108 | netlib: cmake_check_build_system 109 | $(MAKE) -f CMakeFiles/Makefile2 netlib 110 | .PHONY : netlib 111 | 112 | # fast build rule for target. 113 | netlib/fast: 114 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/build 115 | .PHONY : netlib/fast 116 | 117 | # target to build an object file 118 | BaseSocket.o: 119 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/BaseSocket.o 120 | .PHONY : BaseSocket.o 121 | 122 | # target to preprocess a source file 123 | BaseSocket.i: 124 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/BaseSocket.i 125 | .PHONY : BaseSocket.i 126 | 127 | # target to generate assembly for a file 128 | BaseSocket.s: 129 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/BaseSocket.s 130 | .PHONY : BaseSocket.s 131 | 132 | # target to build an object file 133 | EventDispatch.o: 134 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/EventDispatch.o 135 | .PHONY : EventDispatch.o 136 | 137 | # target to preprocess a source file 138 | EventDispatch.i: 139 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/EventDispatch.i 140 | .PHONY : EventDispatch.i 141 | 142 | # target to generate assembly for a file 143 | EventDispatch.s: 144 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/EventDispatch.s 145 | .PHONY : EventDispatch.s 146 | 147 | # target to build an object file 148 | Lock.o: 149 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Lock.o 150 | .PHONY : Lock.o 151 | 152 | # target to preprocess a source file 153 | Lock.i: 154 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Lock.i 155 | .PHONY : Lock.i 156 | 157 | # target to generate assembly for a file 158 | Lock.s: 159 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Lock.s 160 | .PHONY : Lock.s 161 | 162 | # target to build an object file 163 | Netlib.o: 164 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Netlib.o 165 | .PHONY : Netlib.o 166 | 167 | # target to preprocess a source file 168 | Netlib.i: 169 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Netlib.i 170 | .PHONY : Netlib.i 171 | 172 | # target to generate assembly for a file 173 | Netlib.s: 174 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Netlib.s 175 | .PHONY : Netlib.s 176 | 177 | # target to build an object file 178 | Netlib_Test.o: 179 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Netlib_Test.o 180 | .PHONY : Netlib_Test.o 181 | 182 | # target to preprocess a source file 183 | Netlib_Test.i: 184 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Netlib_Test.i 185 | .PHONY : Netlib_Test.i 186 | 187 | # target to generate assembly for a file 188 | Netlib_Test.s: 189 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Netlib_Test.s 190 | .PHONY : Netlib_Test.s 191 | 192 | # target to build an object file 193 | Util.o: 194 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Util.o 195 | .PHONY : Util.o 196 | 197 | # target to preprocess a source file 198 | Util.i: 199 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Util.i 200 | .PHONY : Util.i 201 | 202 | # target to generate assembly for a file 203 | Util.s: 204 | $(MAKE) -f CMakeFiles/netlib.dir/build.make CMakeFiles/netlib.dir/Util.s 205 | .PHONY : Util.s 206 | 207 | # Help Target 208 | help: 209 | @echo "The following are some of the valid targets for this Makefile:" 210 | @echo "... all (the default if no target is provided)" 211 | @echo "... clean" 212 | @echo "... depend" 213 | @echo "... edit_cache" 214 | @echo "... netlib" 215 | @echo "... rebuild_cache" 216 | @echo "... BaseSocket.o" 217 | @echo "... BaseSocket.i" 218 | @echo "... BaseSocket.s" 219 | @echo "... EventDispatch.o" 220 | @echo "... EventDispatch.i" 221 | @echo "... EventDispatch.s" 222 | @echo "... Lock.o" 223 | @echo "... Lock.i" 224 | @echo "... Lock.s" 225 | @echo "... Netlib.o" 226 | @echo "... Netlib.i" 227 | @echo "... Netlib.s" 228 | @echo "... Netlib_Test.o" 229 | @echo "... Netlib_Test.i" 230 | @echo "... Netlib_Test.s" 231 | @echo "... Util.o" 232 | @echo "... Util.i" 233 | @echo "... Util.s" 234 | .PHONY : help 235 | 236 | 237 | 238 | #============================================================================= 239 | # Special targets to cleanup operation of make. 240 | 241 | # Special rule to run CMake to check the build system integrity. 242 | # No rule that depends on this can have commands that come from listfiles 243 | # because they might be regenerated. 244 | cmake_check_build_system: 245 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 246 | .PHONY : cmake_check_build_system 247 | 248 | -------------------------------------------------------------------------------- /Netlib.cpp: -------------------------------------------------------------------------------- 1 | #include "Netlib.h" 2 | #include "BaseSocket.h" 3 | #include "EventDispatch.h" 4 | 5 | int netlib_init() 6 | { 7 | int ret = NETLIB_OK; 8 | #ifdef _WIN32 9 | WSADATA wsaData; 10 | WORD wReqest = MAKEWORDK(1, 1); 11 | if(WSAStartup(wRequest, &wsaData) != 0) 12 | { 13 | ret = NETLIB_ERROR; 14 | } 15 | #endif 16 | 17 | return ret; 18 | } 19 | 20 | int netlib_destroy() 21 | { 22 | int ret = NETLIB_OK; 23 | #ifdef _WIN32 24 | if(WSACleanup() != 0) 25 | { 26 | ret = NETLIB_ERROR; 27 | } 28 | #endif 29 | 30 | return ret; 31 | } 32 | 33 | int netlib_listen( 34 | const char* server_ip, 35 | uint16_t port, 36 | callback_t callback, 37 | void* callback_data) 38 | { 39 | CBaseSocket* pSocket = new CBaseSocket(); 40 | if(!pSocket) 41 | return NETLIB_ERROR; 42 | 43 | int ret = pSocket->Listen(server_ip, port , callback , callback_data); 44 | if(ret == NETLIB_ERROR) 45 | delete pSocket; 46 | 47 | return ret; 48 | } 49 | 50 | net_handle_t netlib_connect( 51 | const char* server_ip, 52 | uint16_t port, 53 | callback_t callback, 54 | void* callback_data) 55 | { 56 | CBaseSocket* pSocket = new CBaseSocket(); 57 | if(!pSocket) 58 | return NETLIB_INVALID_HANDLE; 59 | 60 | net_handle_t handle = pSocket->Connect(server_ip, port, callback, callback_data); 61 | if(handle == NETLIB_INVALID_HANDLE) 62 | delete pSocket; 63 | 64 | return handle; 65 | } 66 | 67 | int netlib_send(net_handle_t handle,void* buf, int len) 68 | { 69 | CBaseSocket* pSocket = FindBaseSocket(handle); 70 | if(!pSocket) 71 | { 72 | return NETLIB_ERROR; 73 | } 74 | 75 | int ret = pSocket->Send(buf, len); 76 | pSocket->ReleaseRef(); 77 | 78 | return ret; 79 | } 80 | 81 | int netlib_recv(net_handle_t handle, void* buf, int len) 82 | { 83 | CBaseSocket* pSocket = FindBaseSocket(handle); 84 | if(!pSocket) 85 | return NETLIB_ERROR; 86 | 87 | int ret = pSocket->Recv(buf, len); 88 | pSocket->ReleaseRef(); 89 | 90 | return ret; 91 | } 92 | 93 | int netlib_close(net_handle_t handle) 94 | { 95 | CBaseSocket* pSocket = FindBaseSocket(handle); 96 | if(!pSocket) 97 | return NETLIB_ERROR; 98 | 99 | int ret = pSocket->Close(); 100 | pSocket->ReleaseRef(); 101 | 102 | return ret; 103 | } 104 | 105 | int netlib_option(net_handle_t handle, int opt, void* optval) 106 | { 107 | CBaseSocket* pSocket = FindBaseSocket(handle); 108 | if(!pSocket) 109 | return NETLIB_ERROR; 110 | 111 | if((opt >= NETLIB_OPT_GET_REMOTE_IP) && !optval) 112 | return NETLIB_ERROR; 113 | 114 | switch(opt) 115 | { 116 | case NETLIB_OPT_SET_CALLBACK: 117 | pSocket->SetCallback((callback_t)optval); 118 | break; 119 | case NETLIB_OPT_SET_CALLBACK_DATA: 120 | pSocket->SetCallbackData(optval); 121 | break; 122 | case NETLIB_OPT_GET_REMOTE_IP: 123 | *(string*)optval = pSocket->GetRemoteIP(); 124 | break; 125 | case NETLIB_OPT_GET_REMOTE_PORT: 126 | *(uint16_t*)optval = pSocket->GetRemotePort(); 127 | break; 128 | case NETLIB_OPT_GET_LOCAL_IP: 129 | *(string*)optval = pSocket->GetLocalIP(); 130 | break; 131 | case NETLIB_OPT_SET_SEND_BUF_SIZE: 132 | pSocket->SetSendBufSize(*(uint32_t*)optval); 133 | break; 134 | case NETLIB_OPT_SET_RECV_BUF_SIZE: 135 | pSocket->SetRecvBufSize(*(uint32_t*)optval); 136 | break; 137 | } 138 | pSocket->ReleaseRef(); 139 | 140 | return NETLIB_OK; 141 | } 142 | 143 | int netlib_register_timer(callback_t callback, void* user_data, uint64_t interval) 144 | { 145 | CEventDispatch::Instance()->AddTimer(callback, user_data, interval); 146 | return 0; 147 | } 148 | 149 | int netlib_delete_timer(callback_t callback, void* user_data) 150 | { 151 | CEventDispatch::Instance()->RemoveTimer(callback, user_data); 152 | return 0; 153 | } 154 | 155 | int netlib_add_loop(callback_t callback, void* user_data) 156 | { 157 | CEventDispatch::Instance()->AddLoop(callback, user_data); 158 | return 0; 159 | } 160 | 161 | void netlib_eventloop(uint32_t wait_timeout) 162 | { 163 | CEventDispatch::Instance()->StartDispatch(wait_timeout); 164 | } 165 | 166 | void netlib_stop_event() 167 | { 168 | CEventDispatch::Instance()->StopDispatch(); 169 | } 170 | 171 | bool netlib_is_running() 172 | { 173 | return CEventDispatch::Instance()->isRunning(); 174 | } 175 | -------------------------------------------------------------------------------- /Netlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __NETLIB_H__ 2 | #define __NETLIB_H__ 3 | 4 | #include "Ostype.h" 5 | 6 | #define NETLIB_OPT_SET_CALLBACK 1 7 | #define NETLIB_OPT_SET_CALLBACK_DATA 2 8 | #define NETLIB_OPT_GET_REMOTE_IP 3 9 | #define NETLIB_OPT_GET_REMOTE_PORT 4 10 | #define NETLIB_OPT_GET_LOCAL_IP 5 11 | #define NETLIB_OPT_GET_LOCAL_PORT 6 12 | #define NETLIB_OPT_SET_SEND_BUF_SIZE 7 13 | #define NETLIB_OPT_SET_RECV_BUF_SIZE 8 14 | 15 | #define NETLIB_MAX_SOCKET_BUF_SIZE (128*1024) 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | int netlib_init(); 22 | int netlib_destroy(); 23 | int netlib_listen( 24 | const char* server_ip, 25 | uint16_t port, 26 | callback_t callback, 27 | void* callback_data); 28 | 29 | net_handle_t netlib_connect( 30 | const char* server_ip, 31 | uint16_t port, 32 | callback_t callback, 33 | void* callback_data); 34 | 35 | int netlib_send(net_handle_t handle, void* buf, int len); 36 | int netlib_recv(net_handle_t handle, void* buf, int len); 37 | int netlib_close(net_handle_t handle); 38 | int netlib_option(net_handle_t handle, int opt, void* optval); 39 | int netlib_register_timer(callback_t callback, void* user_data,uint64_t interval); 40 | int netlib_delete_timer(callback_t callback, void* user_data); 41 | int netlib_add_loop(callback_t callback, void* user_data); 42 | void netlib_eventloop(uint32_t wait_timeout = 100); 43 | void netlib_stop_event(); 44 | bool netlib_is_running(); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /Netlib_Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Netlib.h" 3 | 4 | 5 | void http_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 6 | { 7 | 8 | } 9 | 10 | int main() 11 | { 12 | printf("start....\n"); 13 | signal(SIGPIPE, SIG_IGN); 14 | 15 | 16 | int ret = netlib_init(); 17 | 18 | if( ret == NETLIB_ERROR) 19 | return ret; 20 | 21 | ret = netlib_listen("127.0.0.1", 1111,http_callback, NULL); 22 | printf("now enter the event loop....\n"); 23 | netlib_eventloop(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /Ostype.h: -------------------------------------------------------------------------------- 1 | #ifndef __OS_TYPE_H__ 2 | #define __OS_TYPE_H__ 3 | 4 | #ifdef _WIN32 5 | #include 6 | #include 7 | #include 8 | #include 9 | #else 10 | #ifdef __APPLE__ 11 | #include 12 | #include 13 | #include 14 | #else 15 | #include 16 | 17 | #endif 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #define closesocket close 33 | #define ioctlsocket ioctl 34 | #endif 35 | 36 | #include 37 | 38 | #ifdef __GNUC__ 39 | #include 40 | using namespace __gnu_cxx; 41 | namespace __gnu_cxx{ 42 | template<> struct hash 43 | { 44 | size_t operator()(const std::string& x) const 45 | { 46 | return hash()(x.c_str()); 47 | } 48 | }; 49 | } 50 | 51 | #else 52 | #include 53 | using namespace stdext; 54 | #endif 55 | 56 | #ifdef _WIN32 57 | typedef char int8_t; 58 | typedef short int16_t; 59 | typedef int int32_t; 60 | typedef long long int64_t; 61 | typedef unsigned char uint8_t; 62 | typedef unsigned short uint16_t; 63 | typedef unsigned int uint32_t; 64 | typedef unsigned long long uint64_t; 65 | typedef int socklen_t; 66 | 67 | #else 68 | typedef int SOCKET; 69 | typedef int BOOL; 70 | #ifndef __APPLE__ 71 | const int TRUE = 1; 72 | const int FALSE = 0; 73 | #endif 74 | const int SOCKET_ERROR = -1; 75 | const int INVALID_SOCKET = -1; 76 | #endif 77 | 78 | typedef unsigned char uchar_t; 79 | typedef int net_handle_t; 80 | typedef int conn_handle_t; 81 | 82 | enum 83 | { 84 | NETLIB_OK = 0, 85 | NETLIB_ERROR = -1 86 | }; 87 | 88 | #define NETLIB_INVALID_HANDLE -1 89 | 90 | enum 91 | { 92 | NETLIB_MSG_CONNECT = 1, 93 | NETLIB_MSG_CONFIRM, 94 | NETLIB_MSG_READ, 95 | NETLIB_MSG_WRITE, 96 | NETLIB_MSG_CLOSE, 97 | NETLIB_MSG_TIMER, 98 | NETLIB_MSG_LOOP 99 | }; 100 | 101 | const uint32_t INVALID_UINT32 = (uint32_t) -1; 102 | const uint32_t INVALID_VALUE = 0; 103 | 104 | typedef void (*callback_t) (void* callback_data, uint8_t msg, uint32_t handle, void* pParam); 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # netlib 2 | 简单的跨平台网络通信库 3 | 4 | 编译方式: 5 | 6 | 方法一: 7 | 直接运行./build.sh 8 | 9 | 方法二: 10 | 1)、执行cmake . 11 | $cmake . 12 | 2)、执行make 13 | $make 14 | -------------------------------------------------------------------------------- /Util.cpp: -------------------------------------------------------------------------------- 1 | #include "Util.h" 2 | #include 3 | using namespace std; 4 | 5 | //CSLog g_imLog = CSLog(LOG_MODULE_IM); 6 | 7 | CRefObject::CRefObject() 8 | { 9 | m_lock = NULL; 10 | m_refCount = 1; 11 | } 12 | 13 | CRefObject::~CRefObject() 14 | { 15 | } 16 | 17 | void CRefObject::AddRef() 18 | { 19 | if(m_lock) 20 | { 21 | m_lock->lock(); 22 | m_refCount++; 23 | m_lock->unlock(); 24 | } 25 | else 26 | { 27 | m_refCount++; 28 | } 29 | } 30 | 31 | void CRefObject::ReleaseRef() 32 | { 33 | if(m_lock) 34 | { 35 | m_lock->lock(); 36 | m_refCount--; 37 | if(m_refCount == 0) 38 | { 39 | delete this; 40 | return; 41 | } 42 | m_lock->unlock(); 43 | } 44 | else 45 | { 46 | m_refCount--; 47 | if(m_refCount == 0) 48 | delete this; 49 | } 50 | } 51 | 52 | 53 | uint64_t get_tick_count() 54 | { 55 | #ifdef _WIN32 56 | LARGE_INTERGER liCounter; 57 | LARGE_INTERGER liCurrent; 58 | 59 | if(!QueryPerformanceFrequency(&liCounter)) 60 | return GetTickCount(); 61 | 62 | QueryPerformanceCounter(&liCurrent); 63 | return (uint64_t)(liCurrent.QuadPart * 1000 / liCounter.QuadPart); 64 | #else 65 | struct timeval tval; 66 | uint64_t ret_tick; 67 | 68 | gettimeofday(&tval, NULL); 69 | 70 | ret_tick = tval.tv_sec * 1000L + tval.tv_usec / 1000L; 71 | return ret_tick; 72 | #endif 73 | } 74 | 75 | void util_sleep(uint32_t millisecond) 76 | { 77 | #ifdef _WIN32 78 | Sleep(millisecond); 79 | #else 80 | usleep(millisecond* 1000); 81 | #endif 82 | } 83 | 84 | 85 | CStrExplode::CStrExplode(char* str, char seperator) 86 | { 87 | m_item_cnt = 1; 88 | char* pos = str; 89 | while(*pos) 90 | { 91 | if(*pos == seperator) 92 | { 93 | m_item_cnt++; 94 | } 95 | pos++; 96 | } 97 | 98 | m_item_list = new char*[m_item_cnt]; 99 | 100 | int idx = 0; 101 | char* start = pos = str; 102 | while(*pos) 103 | { 104 | if( pos != start && *pos == seperator) 105 | { 106 | uint32_t len = pos - start; 107 | m_item_list[idx] = new char[len+1]; 108 | strncpy(m_item_list[idx], start, len); 109 | m_item_list[idx][len] = '\0'; 110 | idx++; 111 | 112 | start = pos + 1; 113 | } 114 | pos++; 115 | } 116 | 117 | uint32_t len = pos - start; 118 | if( len != 0) 119 | { 120 | m_item_list[idx] = new char[len + 1]; 121 | strncpy(m_item_list[idx], start, len); 122 | m_item_list[idx][len] = '\0'; 123 | } 124 | } 125 | 126 | 127 | CStrExplode::~CStrExplode() 128 | { 129 | for(uint32_t i = 0; i < m_item_cnt; i++) 130 | { 131 | delete [] m_item_list[i]; 132 | } 133 | 134 | delete [] m_item_list; 135 | } 136 | 137 | char* replaceStr(char* pSrc, char oldChar, char newChar) 138 | { 139 | if( NULL == pSrc) 140 | { 141 | return NULL; 142 | } 143 | 144 | char* pHead = pSrc; 145 | while(*pHead != '\0') 146 | { 147 | if(*pHead == oldChar) 148 | { 149 | *pHead = newChar; 150 | } 151 | ++pHead; 152 | } 153 | return pSrc; 154 | } 155 | 156 | string int2string(uint32_t user_id) 157 | { 158 | stringstream ss; 159 | ss <9?x-10+'A':x+'0'; 202 | } 203 | 204 | inline unsigned char fromHex(const unsigned char &x) 205 | { 206 | return isdigit(x) ? x- '0' : x-'A' + 10; 207 | } 208 | 209 | string URLEncode(const string &sIn) 210 | { 211 | string sOut; 212 | for( size_t ix = 0; ix < sIn.size(); ix++) 213 | { 214 | unsigned char buf[4]; 215 | memset(buf, 0, 4); 216 | if(isalnum((unsigned char)sIn[ix])) 217 | { 218 | buf[0] = sIn[ix]; 219 | } 220 | else 221 | { 222 | buf[0] = '%'; 223 | buf[1] = toHex((unsigned char)sIn[ix] >> 4); 224 | buf[2] = toHex((unsigned char)sIn[ix] % 16); 225 | } 226 | sOut += (char*)buf; 227 | } 228 | return sOut; 229 | } 230 | 231 | string URLDecode(const string&sIn) 232 | { 233 | string sOut; 234 | for( size_t ix = 0; ix < sIn.size(); ix++) 235 | { 236 | unsigned char ch = 0; 237 | if(sIn[ix] == '%') 238 | { 239 | ch = (fromHex(sIn[ix+1]) << 4); 240 | ch |= fromHex(sIn[ix+2]); 241 | ix += 2; 242 | } 243 | else if(sIn[ix] == '+') 244 | { 245 | ch = ' '; 246 | } 247 | else 248 | { 249 | ch = sIn[ix]; 250 | } 251 | sOut += (char)ch; 252 | } 253 | return sOut; 254 | } 255 | 256 | int64_t get_file_size(const char* path) 257 | { 258 | int64_t filesize = -1; 259 | struct stat statbuff; 260 | if(stat(path, &statbuff) < 0) 261 | { 262 | return filesize; 263 | } 264 | else 265 | { 266 | filesize = statbuff.st_size; 267 | } 268 | return filesize; 269 | } 270 | 271 | 272 | -------------------------------------------------------------------------------- /Util.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTIL_H__ 2 | #define __UTIL_H__ 3 | 4 | #define _CRT_SECURE_NO_DEPRECATE //remove warning C4996 5 | 6 | #include "Ostype.h" 7 | //#include "UtilPdu.h" 8 | #include "Lock.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | //#include "slog/slog_api.h" 15 | #ifndef _WIN32 16 | #include 17 | #endif 18 | 19 | #include 20 | #include 21 | 22 | #ifdef _WIN32 23 | #define snprintf sprintf_s 24 | #else 25 | #include 26 | #include 27 | #include 28 | #include 29 | #endif 30 | 31 | using namespace std; 32 | 33 | #define NOTUSED_AGR(v) ((void)v) //used this to remove warning C4100,unreferencded parameter 34 | 35 | class CRefObject 36 | { 37 | public: 38 | CRefObject(); 39 | virtual ~CRefObject(); 40 | 41 | void SetLock(CLock* lock) { m_lock = lock;} 42 | void AddRef(); 43 | void ReleaseRef(); 44 | private: 45 | int m_refCount; 46 | CLock* m_lock; 47 | }; 48 | 49 | //extern CSLog g_imlog; 50 | 51 | #define __FILENAME__ (strrchr(__FILE__,'/') ? (strrchr(__FILE__,'/') + 1):__FILE__) 52 | #if defined (_WIN32) || defined(_WIN64) 53 | //#define log(fmt,...) g_imlog.Info("<%s>\t<%d>\t<%s>,"fmt,__FILENAME__,__LINE__,__FUNCTION__,##__va_args__) 54 | #else 55 | //#define log(fmt, args...) g_imlog.Info("<%s>|<%d>|<%s>,"fmt,__FILENAME__,__LINE__,__FUNCTION__,##args) 56 | #endif 57 | 58 | uint64_t get_tick_count(); 59 | void util_sleep(uint32_t millisecond); 60 | 61 | class CStrExplode 62 | { 63 | public: 64 | CStrExplode(char* str, char seperator); 65 | virtual ~CStrExplode(); 66 | 67 | uint32_t GetItemCnt() { return m_item_cnt;} 68 | char* GetItem(uint32_t idx) { return m_item_list[idx];} 69 | private: 70 | uint32_t m_item_cnt; 71 | char** m_item_list; 72 | }; 73 | 74 | char* replaceStr(char* pStr, char oldChar, char newChar); 75 | string int2string(uint32_t user_id); 76 | uint32_t string2int(const string& value); 77 | void replace_mark(string& str, string& new_value, uint32_t & begin_pos); 78 | void replace_mark(string& str, uint32_t new_value, uint32_t& begin_pos); 79 | 80 | void writePid(); 81 | inline unsigned char toHex(const unsigned char &x); 82 | inline unsigned char fromHex(const unsigned char &x); 83 | 84 | string URLEncode(const string &sIn); 85 | string URLDecode(const string &sIn); 86 | 87 | int64_t get_file_size(const char* path); 88 | const char* memfind(const char* src_str,size_t src_len, const char* sub_str, size_t sub_len, bool flag = true); 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | g++ Lock.h Lock.cpp EventDispatch.h EventDispatch.cpp BaseSocket.h BaseSocket.cpp Util.h Util.cpp Ostype.h Netlib.h Netlib.cpp Netlib_Test.cpp -o netlib -lpthread 2 | -------------------------------------------------------------------------------- /netlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharmingZhou/netlib/77697207d0b7a0db23599c1a4f603d40b35b2084/netlib --------------------------------------------------------------------------------