#define _WSPIAPI_H_ #define _WINSOCKAPI_ #include "tcp_server_libevent.h" #include /** * @description: * @param {*} * @return {*} */ ConnectionLibevent::ConnectionLibevent(TcpServerLibevent *p,struct bufferevent *ev,uint32_t fd,struct sockaddr_in *p1): m_parent_server(nullptr), m_event(nullptr), m_fd(-1), m_addr(nullptr) { m_parent_server = p; m_event = ev; m_fd = fd; m_addr = p1; } /** * @description: * @param {*} * @return {*} */ ConnectionLibevent::ConnectionLibevent(struct bufferevent *ev,uint32_t fd,struct sockaddr_in *p1): m_parent_server(nullptr), m_event(nullptr), m_fd(-1), m_addr(nullptr) { m_event = ev; m_fd = fd; m_addr = p1; } /** * @description: * @param {*} * @return {*} */ ConnectionLibevent* defaultConnAccept(struct bufferevent *ev,uint32_t fd,struct sockaddr_in *p1){ return new ConnectionLibevent(ev,fd,p1); } /** * @description: * @param {*} * @return {*} */ int ConnectionLibevent::OnRecv(char *p,uint32_t len){ std::cout<<"OnRecv "<m_fd << " "<IpAddress()<m_event,p,len); } uint32_t ConnectionLibevent::SocketFd(){ return m_fd; } /** * @description: * @param {*} * @return {*} */ int ConnectionLibevent::SetServer(TcpServerLibevent *p){ if(nullptr != p){ this->m_parent_server = p; return 0; } return -1; } string ConnectionLibevent::IpAddress(){ if(nullptr != m_addr){ return string(inet_ntoa(m_addr->sin_addr)); } return ""; } TcpServerLibevent *ConnectionLibevent::Server(){ return m_parent_server; } void read_cb(struct bufferevent *bev, void *arg) { char buf[1024] = {0}; ConnectionLibevent* conn = (ConnectionLibevent*)arg; bufferevent_read(bev, buf, sizeof(buf)); auto server = conn->Server(); emit(server->on_conn_read("12345")); cout << "client " << conn->IpAddress() << " say:" << buf << endl; conn->OnRecv(buf,sizeof(buf)); } void write_cb(struct bufferevent *bev, void *arg) { ConnectionLibevent* conn = (ConnectionLibevent*)arg; std::cout<<"connection "<IpAddress()<<" sended data success"<< std::endl; } /** * @description: * @param {*} * @return {*} */ void event_cb(struct bufferevent *bev, short events, void *arg) { ConnectionLibevent *conn = (ConnectionLibevent*)(arg); TcpServerLibevent *server = conn->Server(); if (events & BEV_EVENT_EOF) { cout << "connection closed: " << conn->IpAddress() << " " << conn->SocketFd() << endl; conn->OnClose(); bufferevent_free(bev); server->RemoveConnection(conn->SocketFd()); } else if (events & BEV_EVENT_ERROR) { conn->OnClose(); bufferevent_free(bev); server->RemoveConnection(conn->SocketFd()); cout << "some other error !" << endl; } delete conn; } /** * @description: * @param {*} * @return {*} */ void cb_listener(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int len, void *ptr) { struct sockaddr_in* client = (sockaddr_in*)addr ; cout << "connect new client: " << inet_ntoa(client->sin_addr) << " " << fd << " ::"<< ntohs(client->sin_port)<< endl; TcpServerLibevent *server = (TcpServerLibevent*)ptr; if(server != nullptr){ struct bufferevent *bev; bev = bufferevent_socket_new(server->m_event_base, fd, BEV_OPT_CLOSE_ON_FREE); ConnectionLibevent *conn = server->m_handle_accept(bev,ntohs(client->sin_port),client); conn->SetServer(server); server->AddConnection(ntohs(client->sin_port),conn); bufferevent_setcb(bev, read_cb, write_cb, event_cb, conn); bufferevent_enable(bev, EV_READ); } } /** * @description: * @param {*} * @return {*} */ void server_run(TcpServerLibevent *p){ if(nullptr != p){ while(p->m_status == TcpServerLibevent::RUNNING){ int ret =event_base_loop(p->m_event_base,EVLOOP_NONBLOCK); if(ret < 0){ p->m_status = TcpServerLibevent::FAIL; break; } } } } /** * @description: * @param {*} * @return {*} */ TcpServerLibevent::SERVER_STATUS TcpServerLibevent::Status(){ return m_status; } /** * @description: * @param {*} * @return {*} */ int TcpServerLibevent::AddConnection(uint32_t fd,ConnectionLibevent *p){ if( m_map_client.find(fd) == m_map_client.end()){ if(nullptr != p) m_map_client[fd] = p; else return -1; } emit(this->on_onnected(p->IpAddress(),p->SocketFd())); return 0; } /** * @description: * @param {*} * @return {*} */ int TcpServerLibevent::RemoveConnection(uint32_t fd){ if( m_map_client.find(fd) != m_map_client.end()){ emit(on_disconected(m_map_client.at(fd)->IpAddress(), m_map_client.at(fd)->SocketFd())); m_map_client.erase(fd); return 0; }else{ return -1; } } /** * @description: * @param {*} * @return {*} */ int TcpServerLibevent::SetNewConnectionHandle(OnAccept p){ m_handle_accept = p; return 0; } /** * @description: * @param {int} ports * @param {string} bindip * @return {*} */ TcpServerLibevent::TcpServerLibevent(int port,string bindip) : m_thread(nullptr), m_event_base(nullptr), m_event_listener(nullptr) { m_handle_accept = defaultConnAccept; m_backlog = 10000; this->m_bind_ip = bindip; this->m_port = port; memset(&m_server_addr, 0, sizeof(m_server_addr)); m_server_addr.sin_family = AF_INET; m_server_addr.sin_port = htons(port); m_server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 创建 event_base m_event_base = event_base_new(); if(NULL == m_event_base){ return; } m_event_listener = evconnlistener_new_bind(m_event_base, cb_listener, this, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_THREADSAFE, m_backlog, (struct sockaddr*)&m_server_addr, sizeof(m_server_addr)); if(NULL == m_event_listener) { m_status = FAIL; } m_status = STOP; } /** * @description: start server synchronous * @param {*} * @return {*} */ int TcpServerLibevent::StartServerSync(){ if(m_status == STOP){ m_status = RUNNING; if(-1 == event_base_dispatch(m_event_base)){ qDebug()<<"error "; } event_base_free(m_event_base); return 0; } return -1; } /** * @description: start server asynchronous * @param {*} * @return {*} */ int TcpServerLibevent::StartServerAsync(){ if(m_status == STOP){ #ifdef WIN32 evthread_use_windows_threads(); #endif #ifdef linux evthread_use_pthreads(); #endif m_status = RUNNING; m_thread = new std::thread(server_run,this); m_thread->detach(); return 0; } return -1; } int TcpServerLibevent::StopServer() { struct timeval v; v.tv_usec = 1000; v.tv_sec = 0; if(m_status == RUNNING){ int ret = event_base_loopexit(m_event_base,&v); if (ret < 0){ // todo write log } evconnlistener_free(this->m_event_listener); if(ret < 0){ // todo write log qDebug()<<"evconnlistener_disable"<m_status == RUNNING){ m_thread->detach(); struct timeval v; v.tv_usec = 1000; v.tv_sec = 1; int ret = event_base_loopexit(m_event_base,&v); this->m_status = STOP; } if(nullptr != m_event_base){ event_base_free(m_event_base); delete m_event_base; m_event_base = nullptr; } if(nullptr != m_event_listener){ delete m_event_listener; m_event_listener = nullptr; } }