#include #include #include #include #include #include #include #include #include #include "Socket.h" #include "debug.h" #include "MessageHandle.h" #include "EpollThread.h" #define TIMER_INTERVAL 5 #define TIMER_EXPIRE 60 //////////////////////////////////////////////////////////////////////////////// //HandlerThread EpollHandler::HandlerThread::HandlerThread(EpollHandler* pHandler, CSema* pSema) : CThread(3000) { m_pHandler = pHandler; m_pSema = pSema; } void EpollHandler::HandlerThread::Main() { while(!m_bExit){ RECVBUFF* pRB = m_pHandler->GetBuff(); if(pRB){ // send(pRB->socket, pRB->buffer, pRB->buffsize, 0); TNETMESSAGE msgRequest; if( !m_bExit && ReadNetMessage( (unsigned char*)pRB->buffer, pRB->buffsize, &msgRequest )){ TNETMESSAGE msgResponse; struct sockaddr_in peerAddr; UINT peerLen = sizeof(peerAddr); if( getpeername(pRB->socket, (struct sockaddr *)&peerAddr, &peerLen)<0 ){ DebugPrint("getpeername error: %d", errno); } USHORT peerPort = ntohs(peerAddr.sin_port); if(msgRequest.iExtra < 0x0D00){ memcpy(msgRequest.idDevice, &peerAddr.sin_addr, 4); memcpy(msgRequest.idDevice+4, &peerAddr.sin_port, 2); } else{ memcpy(msgResponse.idDevice, msgRequest.idDevice, 6); } // if( msgRequest.eMessageType==e_versionRequest ){ // DebugPrint( "CONNECT %s:%d type: TCP", inet_ntoa(peerAddr.sin_addr), peerPort ); // } if( !m_bExit && HandleRequest( &msgRequest, &msgResponse, peerAddr.sin_addr.s_addr, peerPort ) ){ short nSize = DATA_BUFSIZE; if( !m_bExit && WriteNetMessage( (unsigned char*)pRB->buffer, nSize, &msgResponse ) ){ if( send(pRB->socket, pRB->buffer, nSize, 0) == SOCKET_ERROR){ DebugPrint("send() failed with error %d", errno); } } } } delete pRB; } else{ m_pSema->ActP(); } } DebugPrint("EpollHandlerThread exit"); } /////////////////////////////////////////////////////////////////////////////// //EpollHandler EpollHandler::EpollHandler() : m_smProcess(NULL, 0), m_smBuffers(NULL, 1) { for(int i=0; iResume(); } } EpollHandler::~EpollHandler() { for(int i=0; iTerminate(); } //Release sema individully for(int i=0; iTerminate(); } void EpollThread::Main() { //创建一个监听socket int listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); if (listenfd == -1){ DebugPrint("create listen socket error"); return; } //设置重用ip地址和端口号 int on = 1; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char*)& on, sizeof(on)); setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (char*)& on, sizeof(on)); //初始化服务器地址 struct sockaddr_in bindaddr; bindaddr.sin_family = AF_INET; bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); bindaddr.sin_port = htons(LISTEN_PORT); if (bind(listenfd, (struct sockaddr*) & bindaddr, sizeof(bindaddr)) == -1) { close(listenfd); DebugPrint("bind listen socker error."); return; } //启动监听 if (listen(listenfd, SOMAXCONN) == -1){ close(listenfd); DebugPrint("listen error."); return; } //创建epollfd int epollfd = epoll_create1(EPOLL_CLOEXEC); if (epollfd == -1){ DebugPrint("create epollfd error."); close(listenfd); return; } epoll_event listen_fd_event; listen_fd_event.data.fd = listenfd; listen_fd_event.events = EPOLLIN; //将监听sokcet绑定到epollfd上去 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &listen_fd_event) == -1){ DebugPrint("epoll_ctl error"); close(listenfd); return; } if(m_fdPipe[0]){ struct epoll_event ev; ev.data.fd = m_fdPipe[0]; ev.events = EPOLLIN; //水平触发方式,监听可读事件,即管道有数据可以读取了 if(epoll_ctl(epollfd, EPOLL_CTL_ADD, m_fdPipe[0], &ev)<0){ DebugPrint("epoll_ctl_add pipe error: %d", errno); } } int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if(timerfd!=-1 ){ struct itimerspec newValue = {}; newValue.it_interval.tv_sec = TIMER_INTERVAL; newValue.it_value.tv_sec = TIMER_INTERVAL; if(timerfd_settime(timerfd, 0, &newValue, NULL)==-1){ DebugPrint("settime error"); close(timerfd); } else{ epoll_event timer_event; timer_event.data.fd = timerfd; timer_event.events = EPOLLIN; if(epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &timer_event)<0){ DebugPrint("epoll_ctl_add timer error: %d", errno); close(timerfd); } } } map mapFds; //tcp连接组 int maxCount = 0; epoll_event epoll_events[1024]; char dataBuff[DATA_BUFSIZE]; while(!m_bExit){ int n = epoll_wait(epollfd, epoll_events, 1024, -1); if(n < 0){ //被信号中断 if (errno == EINTR) continue; //出错,退出 DebugPrint("epoll exit with error: %d", errno); break; } for (int i = 0; i < n && !m_bExit; ++i) { if (epoll_events[i].data.fd == m_fdPipe[0]){ //exit signal DebugPrint("Got epoll exit signal"); break; } else if (epoll_events[i].data.fd == timerfd){ // DebugPrint("epoll timer on"); uint64_t exp=0; if(read(timerfd, &exp, sizeof(uint64_t))!=sizeof(uint64_t)){ close(timerfd); } int count = 0; for(auto it=mapFds.begin(); it!=mapFds.end();){ it->second += TIMER_INTERVAL; if( it->second >= TIMER_EXPIRE ){//空闲1分钟关闭 close(it->first); it = mapFds.erase(it); // DebugPrint("close expired socket"); } else{ count++; it++; } } if(count>maxCount){ DebugPrint("mapFds max size: %d", count); maxCount = count; } } else if (epoll_events[i].data.fd == listenfd){ if(epoll_events[i].events & EPOLLIN){//侦听socket,接受新连接 struct sockaddr_in clientaddr; socklen_t clientaddrlen = sizeof(clientaddr); int clientfd = accept4(listenfd, (struct sockaddr*)&clientaddr, &clientaddrlen, SOCK_NONBLOCK|SOCK_CLOEXEC); if (clientfd != -1){ epoll_event client_event; client_event.data.fd = clientfd; client_event.events = EPOLLIN | EPOLLRDHUP;// | EPOLLET; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &client_event) == -1){ DebugPrint("add client fd to epollfd error"); close(clientfd); } // DebugPrint("add client fd %d to epollfd", clientfd); // mapFds.insert(clientfd, 0); mapFds[clientfd] = 0; } } } else if (epoll_events[i].events & EPOLLRDHUP ) { if (epoll_ctl(epollfd, EPOLL_CTL_DEL, epoll_events[i].data.fd, NULL) == -1){ // DebugPrint("EPOLL_CTL_DEL clientfd %d by event %d", epoll_events[i].data.fd, epoll_events[i].events); // } // else{ DebugPrint("EPOLL_CTL_DEL clientfd %d by event %d error", epoll_events[i].data.fd, epoll_events[i].events); } close(epoll_events[i].data.fd); mapFds.erase(mapFds.find(epoll_events[i].data.fd)); } else if (epoll_events[i].events & EPOLLIN){ //事件可读 // DebugPrint("client fd: %d recv data.", epoll_events[i].data.fd); int m = recv(epoll_events[i].data.fd, dataBuff, DATA_BUFSIZE, 0); // DebugPrint("read data size %d", m); if( m>0 && ValidNetMessage((UCHAR*)dataBuff, m) ){ RECVBUFF* pRB = new RECVBUFF; memcpy(pRB->buffer, dataBuff, m); pRB->socket = epoll_events[i].data.fd; pRB->buffsize = m; m_pHandler->AddBuff(pRB); } else if (m <= 0 && errno != EWOULDBLOCK && errno != EINTR){ //对端关闭了连接,从epollfd上移除clientfd if (epoll_ctl(epollfd, EPOLL_CTL_DEL, epoll_events[i].data.fd, NULL) == -1){ // DebugPrint("EPOLL_CTL_DEL clientfd %d normally", epoll_events[i].data.fd); // } // else{ DebugPrint("EPOLL_CTL_DEL clientfd %d by EPOLLIN error", epoll_events[i].data.fd); } close(epoll_events[i].data.fd); mapFds.erase(mapFds.find(epoll_events[i].data.fd)); } mapFds.find(epoll_events[i].data.fd)->second = 0; } } } close(epollfd); DebugPrint("EPOLL main exit"); }