error_code async_listen(const char * pStrIP, s32 nPort, OUT s32 * pnError, void * pData, s32 backlog) { ASSERT(pStrIP != NULL && pnError != NULL); errno = 0; struct epoll_event e; struct cepoll_event * pEvent = NULL; s32 s = socket(AF_INET, SOCK_STREAM, 0); if (-1 == (s = socket(AF_INET, SOCK_STREAM, 0))) { ECHO_ERROR("socket error %d", errno); return false; } //把socket设置为非阻塞方式 if (!Setnonblocking(s)) { ECHO_ERROR("Setnonblocking error %d", errno); return false; } pEvent = malloc_event(); if (NULL == pEvent) { //assert(false); ECHO_ERROR("%s", "get cepoll_event error"); RETURN_RES(ERROR_MALLOC_EVENT); } struct sockaddr_in addr; memset(&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; inet_aton(pStrIp, &(addr.sin_addr)); addr.sin_port = htons(nPort); if (-1 == bind(s, (sockaddr *) & addr, sizeof (addr)) || -1 == (listen(s, LISTEN_QUENE))) { Assert(false); return false; } struct epoll_event ev; ev.data.ptr = pListen; ev.events = EPOLLIN; // | EPOLLET; epoll_ctl(m_epfd, EPOLL_CTL_ADD, listenfd, &ev); return true; }
int main() { int i, maxi, listenfd, connfd, sockfd,epfd; int server_len,client_len; ssize_t n; char line[MAXLINE]; socklen_t clilen; //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件 struct epoll_event ev,events[EVTOTAL]; //生成用于处理accept的epoll专用的文件描述符 epfd=epoll_create(2048); //启动在线用户数统计的线程 pthread_t dm; pthread_attr_t attr={0}; pthread_attr_init (&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); pthread_create(&dm,NULL,dmlog,NULL); struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; //定义每个EPOLL事件的收发消息 char RECV_MSG[100][30]; unsigned long HashTbInd; //生成KEY值密码树1280[0x500]个 prepareCryptTable(); //ShowCryptTable(); ConnMemHashTable("/root/tt",0x07); //printf("HEAD RECORD:%s\n",(RO_HPP+0x81E5E)->Raw_str); listenfd = socket(AF_INET, SOCK_STREAM, 0); //把socket设置为非阻塞方式 Setnonblocking(listenfd); //设置与要处理的事件相关的文件描述符 ev.data.fd=listenfd; //设置要处理的事件类型 ev.events=EPOLLIN|EPOLLET; //注册epoll事件 epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); //设置SOCKET SERVER基本参数 bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; //char *local_addr="192.168.8.108"; //inet_aton(LOCAL_SVADDR,&(serveraddr.sin_addr));//htons(SERV_PORT); serveraddr.sin_addr.s_addr = htons(INADDR_ANY); serveraddr.sin_port=htons(SERV_PORT); bind(listenfd,(struct sockaddr *)&serveraddr, sizeof(serveraddr)); listen(listenfd, LISTENQ); maxi = 0; for (;;) { //等待epoll事件的发生 nfds=epoll_wait(epfd,events,EVTOTAL,-1); //printf("online number:%d\n",nfds); //处理所发生的所有事件 for(i=0;i<nfds;++i) { //printf("epollnum,epolldatafd,epolleventst,listenfd:%d,%d,%d,%d\n",i,events[i].data.fd,events[i].events,listenfd); //如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。 //在EPOLL EVENT中注册新连接 if(events[i].data.fd==listenfd) { client_len = sizeof(clientaddr); connfd = accept(listenfd,(struct sockaddr *)&clientaddr, (socklen_t *)&client_len); if(connfd<0){ perror("connfd<0"); exit(1); } Setnonblocking(connfd); char *str = inet_ntoa(clientaddr.sin_addr); //printf("sourd addr:%s;connfd=%d\n",str,connfd); //设置用于读操作的文件描述符 ev.data.fd=connfd; //设置用于注测的读操作事件 ev.events=EPOLLIN|EPOLLET; //注册ev epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } //如果是已经连接的用户,并且收到数据,那么进行读入。 //把新数据这件事儿在EPOLL EVENT 中注册新FD,如果没数据,则关闭EPOLL.EVENTS.DATA.FD else if(events[i].events&EPOLLIN) { //printf(" IN:events&EPOLLIN&EPOLLOUT=%d,%d,%d\n",events[i].events,EPOLLIN,EPOLLOUT); if ( (sockfd = events[i].data.fd) < 0) continue; if ( (n = read(sockfd, RECV_MSG[i], MAXLINE)) < 0) { if (errno == ECONNRESET) { //usleep(1000); close(sockfd); events[i].data.fd = -1; } else printf("readline error\n"); } else if (n == 0) { //usleep(1000); //close(sockfd); events[i].data.fd = -1; } //printf("%s",RECV_MSG[i]); //设置用于写操作的文件描述符 ev.data.fd=sockfd; //设置用于注册的写操作事件 ev.events=EPOLLOUT|EPOLLET; //修改sockfd上要处理的事件为EPOLLOUT epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if(events[i].events&EPOLLOUT) { //printf("OUT:events&EPOLLIN&EPOLLOUT=%d,%d,%d\n",events[i].events,EPOLLIN,EPOLLOUT); sockfd = events[i].data.fd; HashTbInd=(HashString(RECV_MSG[i],0)%HashTbSize); //printf("%s:%X:%s ",RECV_MSG[i],HashTbInd,(RO_HPP)->Raw_str); printf("%s:%X:%s \n",RECV_MSG[i],HashTbInd,(RO_HPP+HashTbInd)->Raw_str); if ((*(RO_HPP+HashTbInd)).Hash1==HashString(RECV_MSG[i],1)&&((*(RO_HPP+HashTbInd)).bExist==0)) { write(sockfd,(RO_HPP+HashTbInd)->Raw_str,strlen((RO_HPP+HashTbInd)->Raw_str));} else {write(events[i].data.fd,"NO RECORDS",9);} //printf("RECV MSG=%s,SOCKFD=%d,nfds=%d,nfds_i=%d,RESPONSE OK\n",line,events[i].data.fd,nfds,i); //close(sockfd); //设置用于读操作的文件描述符 bzero(RECV_MSG[i],30); ev.data.fd=sockfd; //设置用于注测的读操作事件 ev.events=EPOLLIN|EPOLLET; //close(sockfd); //修改sockfd上要处理的事件为EPOLIN epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } } } }