int main(int argc, char *argv[]){ if(argc <= 2){ printf("usage: %s ip_address port_number\n", basename(argv[0])); return 1; } const char* ip = argv[1]; int port = atoi(argv[2]); struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET, ip, &address.sin_addr); address.sin_port = htons(port); int listenfd = socket(PF_INET, SOCK_STREAM, 0); assert(listenfd >= 0); int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address)); assert(ret != -1); ret = listen(listenfd, 5); assert(ret != -1); epoll_event events[MAX_EVENT_NUMBER]; int epollfd = epoll_create(5); assert(epollfd != 0); addfd(epollfd, listenfd); ret = socketpair(PF_UNIX, SOCK_STREAM, 0, pipefd); assert(ret != -1); setnonblocking(pipefd[1]); addfd(epollfd, pipefd[0]); /*设置信号处理函数*/ addsig(SIGALARM); addsig(SIGTERM); bool stop_server = false; client_data* users = new client_data[FD_LIMIT]; bool timeout = false; alarm(TIMESLOT); /*定时*/ while(!stop_server){ int number = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1); if(number < 0 && errno != EINTR){ printf("epoll failed\n"); break; } for(int i = 0; i < number; i++){ int sockfd = events[i].data.fd; if(sockfd == listenfd){ struct sockaddr_in client_address; socklen_t client_addrlength = sizeof(client_address); int connfd = accept(sockfd, (struct sockaddr*)&client_address, &client_addrlength); addfd(epollfd, connfd); users[connfd].address = client_address; users[connfd].sockfd = connfd; util_timer* timer = new util_timer; timer->client_data = users[connfd]; timer->cb_func = cb_func; time_t cur = time(NULL); timer->expire = cur + 3*TIMESLOT; users[connfd].timer = timer; timer_lst.add_timer(timer); } else if((sockfd == pipefd[0]) && (events[i].events & EPOLLIN)){ char signals[1024]; memset(signals, '\0', sizeof(signals)); ret = recv(pipefd[0], signals, sizeof(signals), 0); if(ret < 0){ //handle the error continue; } else if(ret == 0){ continue; } else { for(int i = 0; i < ret; i++){ switch (signals[i]) case SIGALARM: /*关闭长时间不响应的连接*/ timeout = true;//不立即处理定时任务 break; case SIGTERM: stop_server = true; } } } else if(events[i].events & EPOLLIN){ memset(users[sockfd].buf, '\0', BUFFER_SIZE); ret = recv(sockfd, users[sockfd].buf, BUFFER_SIZE - 1, 0); util_timer* timer = users[sockfd].timer; if(ret < 0){ if(errno != EAGAIN){ /*发生错误,则关闭连接,并移除定时器*/ cb_func(&users[sockfd]); if(timer){ timer_lst.del_timer(timer); } } } else if(ret == 0){ /*对方已关闭连接,则关闭连接,并移除定时器*/ cb_func(&users[sockfd]); if(timer){ timer_lst.del_timer(timer); } } else { printf("get %d bytes of client data %s from %d\n", ret, users[sockfd].buf, sockfd); /*有数据,则需要调整定时器,以延迟该连接被关闭的时间*/ if(timer){ time_t cur = time(NULL); timer->expire = cur + 3*TIMESLOT; printf("adjust timer once\n"); timer_lst.adjust_timer(timer); } } } else { //others } } /*最后处理定时事件*/ if(timeout){ timer_handler(); timeout = false; } } close(listenfd); close(pipefd[0]); close(pipefd[1]); delete[] users; return 0; }
int main(int argc, char *argv[]) { bool stop_server = false; client_data *users; bool timeout = false; int epollfd; epoll_event events[MAX_EVENT_NUMBER]; int listenfd; int ret = 0; struct sockaddr_in address; const char *ip; int port; if (argc < 2) { printf("usage: ./main ip_address port_number"); return 1; } ip = argv[1]; port = atoi(argv[2]); bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET, ip, &address.sin_addr); address.sin_port = htons(port); listenfd = socket(PF_INET, SOCK_STREAM, 0); assert(listenfd >= 0); ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address)); assert(ret != -1); ret = listen(listenfd, 5); assert(ret != -1); epollfd = epoll_create(5); assert(epollfd != -1); addfd(epollfd, listenfd); ret = socketpair(PF_UNIX, SOCK_STREAM, 0, pipefd); assert(ret != -1); setnonblocking(pipefd[1]); addfd(epollfd, pipefd[0]); addsig(SIGALRM); addsig(SIGTERM); users = new client_data[FD_LIMIT]; alarm(TIMESLOT); while (!stop_server) { int number = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1); if ((number < 0) && (errno != EINTR)) { printf("epoll failure\n"); break; } for (int i=0; i<number; ++i) { int sockfd = events[i].data.fd; if (sockfd == listenfd) { struct sockaddr_in client_address; socklen_t client_addlength = sizeof(client_address); int connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addlength); addfd(epollfd, connfd); users[connfd].address = client_address; users[connfd].sockfd = connfd; util_timer *timer = new util_timer; timer->user_data = &users[connfd]; timer->cb_func = cb_func; time_t cur = time(NULL); timer->expire = cur + TIME_INACTIVE; users[connfd].timer = timer; timer_lst.add_timer(timer); } else if ((sockfd == pipefd[0]) && (events[i]).events & EPOLLIN) { char signals[1024]; ret = recv(pipefd[0], signals, sizeof(signals), 0); if (ret == -1) continue; else if (ret == 0) continue; else { for (int i=0; i<ret; ++i) { switch (signals[i]) { case SIGALRM: timeout = true; break; case SIGTERM: stop_server = true; } } } } else if (events[i].events & EPOLLIN) { util_timer *timer = users[sockfd].timer; memset(users[sockfd].buf, '\0', BUFFER_SIZE); ret = recv(sockfd, users[sockfd].buf, BUFFER_SIZE, 0); if (ret < 0) { if (errno != EAGAIN) { cb_func(&users[sockfd]); if (timer) timer_lst.del_timer(timer); } } else { users[sockfd].buf[ret-1] = '\0'; printf("get %d bytes of client data %s from %d\n", ret, users[sockfd].buf, sockfd); if (timer) { time_t cur = time(NULL); timer->expire = cur + TIME_INACTIVE; timer_lst.adjust_timer(timer); } } } } if (timeout) { timer_handler(); timeout = false; } } close(listenfd); close(pipefd[0]); close(pipefd[1]); delete []users; return 0; }
void timer_handler(){ /*定时处理任务:删除到期定时器并执行回调函数*/ timer_lst.tick(); /*因为一次alarm调用只会引起一次SIGALARM信号,所以要重新定时,以不断触发SIGALARM信号*/ alarm(TIMESLOT); }
void timer_handler() { timer_lst.tick(); alarm(TIMESLOT); }