epolltest.cpp :
#include #include #include #include #include #include #include #include #include #define MAX_EPOLL_FD_NUM 20000 #define SEND_BUFFER_LEN 1024 #define RECV_BUFFER_LEN 1024 int nb_socket(int domain, int type, int protocol) { int sfd = socket(domain, type, protocol), flags = 1; if (sfd == -1) return -1; if(ioctl(sfd, FIONBIO, &flags) && ((flags = fcntl(sfd, F_GETFL, 0)) < 0 || fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0)) { close(sfd); return -1; } return sfd; } int main() { int epollfd; int triggered; int i; struct epoll_event *events; struct epoll_event *cevents; struct epoll_event ev; unsigned short port = 8008; struct sockaddr_in addr; int listenfd, flags = 1; struct linger ling = {0, 0}; int socks; time_t now; char recvbuffer[1024]; int bytes; unsigned int pkgs; printf("程序开始执行....创建侦听套接字../n"); if ((listenfd = nb_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { printf("失败。。。。呜呜..!"); return 3; } setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags)); setsockopt(listenfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); printf("侦听套接字ID:%d/n",listenfd); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listenfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { close(listenfd); return 4; } listen(listenfd, 1024); printf("准备创建EPoll端口...../n"); if((epollfd = epoll_create(MAX_EPOLL_FD_NUM)) < 0) { perror("epoll_create"); close(listenfd); return -1; } printf("EPoll端口创建完成...端口号:%d/n",epollfd); events = (struct epoll_event *)malloc(MAX_EPOLL_FD_NUM * sizeof(struct epoll_event)); printf("将侦听套接字绑定到EPoll端口..../n"); ev.data.fd = listenfd; ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; if(epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) { printf("epoll set insertion error: listen socket fd=%d/n", listenfd); free(events); close(epollfd); close(listenfd); return 5; } printf("侦听套接字绑定到EPoll端口完成...进入事件触发等待/n"); socks = 1; for(int k = 0 ; k < 100; k ++) { triggered = epoll_wait(epollfd, events, MAX_EPOLL_FD_NUM, -1); printf("事件数:%d/n",triggered); for(i=0; ievents & (EPOLLERR | EPOLLHUP)) { printf("POLLERR | POLLHUP fd = %d/r/n", cevents->data.fd); epoll_ctl(epollfd, EPOLL_CTL_DEL, cevents->data.fd, NULL); close(cevents->data.fd); socks--; continue ; } if(cevents->events & EPOLLIN) { if(cevents->data.fd == listenfd) { struct sockaddr_in addr; int len; int sfd; len = sizeof(addr); if((sfd = accept(listenfd, (struct sockaddr*)&addr, (socklen_t*)&len)) == -1) { perror("accept"); continue; } ev.data.fd = sfd; ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; epoll_ctl(epollfd, EPOLL_CTL_ADD, sfd, &ev); socks++; printf("accpet a connection %s:%d/r/n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); continue; } bytes = read(cevents->data.fd, recvbuffer, sizeof(recvbuffer)); if(bytes > 0) { printf("套接字:%d,收到字符:%s/t对它注册发送事件./n",cevents->data.fd,recvbuffer); ev.data.fd = cevents->data.fd; ev.events = EPOLLOUT; if(epoll_ctl(epollfd, EPOLL_CTL_MOD, cevents->data.fd, &ev) == -1) { perror("对方有数据到来时,这边添加发送事件出错../n"); printf("对套接字:%d,注册发送事件失败.../n",cevents->data.fd); continue ; } } else { printf("套接字:%d,被关闭,注销事件。/n",cevents->data.fd); ev.data.fd = cevents->data.fd; ev.events = EPOLLOUT|EPOLLIN|EPOLLERR|EPOLLHUP; if(epoll_ctl(epollfd, EPOLL_CTL_DEL, cevents->data.fd, &ev) == -1) { perror("对方关闭时,这边注销事件出错../n"); printf("对套接字:%d,注销所有事件失败.../n",cevents->data.fd); close(cevents->data.fd); continue ; } printf("关闭该套接字.."); close(cevents->data.fd); } } if(cevents->events & EPOLLOUT) { printf("套接字:%d,有发送事件...现在将该套接字发送事件删除。/n",cevents->data.fd); send(cevents->data.fd,recvbuffer,bytes,0); ev.data.fd = cevents->data.fd; ev.events = EPOLLIN|EPOLLERR|EPOLLHUP; if(epoll_ctl(epollfd, EPOLL_CTL_MOD, cevents->data.fd, &ev) == -1) { perror("可以对套接字发送数据时,这边删除发送事件出错../n"); printf("对套接字:%d,注册发送事件失败.../n",cevents->data.fd); continue ; } } } } return 0; }
makefile :
#------------------------------------------------------------------------------ # 路径 #------------------------------------------------------------------------------ # include INC_BOOST = -I/usr/local/include/boost-1_32 INC_POLLER = -I./include INC_SYS = -I/usr/include #------------------------------------------------------------------------------ # lib LIB_BOOST = -L/usr/local/lib -lboost_thread-gcc-mt -lboost_date_time-gcc-mt LIB_LOG4CPLUS = -L/usr/local/lib -llog4cplus #------------------------------------------------------------------------------ # 开发环境的定义 C_FLAGS = -g -Wall -pthread -ftemplate-depth-20 -DDEBUG #-DUSE_LOG4CPLUS LD_FLAGS = CC = gcc CXX = g++ RANLIB = ranlib AR = ar INC = $(INC_POLLER) #$(INC_BOOST) LIB = $(LIB_LOG4CPLUS) #$(LIB_BOOST) BINNAME = epolltest SRCS = $(wildcard *.cpp) OBJS = $(patsubst %.cpp,%.o,$(SRCS)) all:$(BINNAME) $(BINNAME):$(OBJS) $(CXX) $(C_FLAGS) -o $(BINNAME) *.o %.o:%.cpp $(CXX) $(C_FLAGS)$(INC) $(INC_SYS) -o $@ -c $< clean: rm -fr *.o $(BINNAME)