#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/socket.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <sys/epoll.h> #include <errno.h> #include "common.h" #include "serversignal.h" #include "server_epoll.h" static int open_socket(struct sockaddr_in* paddr); static int accept_client(int sockfd, struct sockaddr_in* paddr); static int process_request(int connfd); static volatile sig_atomic_t graceful=0; #define HTTP_PORT 18080 #define BACK_LOG 50 #define MAX_FDS 100 #define SOCKLEN sizeof(struct sockaddr_in) #define err_log_exit() do{ perror("server failed"); fprintf(stderr, "file %s line %d\n", __FILE__, __LINE__); exit(EXIT_FAILURE); }while(0) #define err_msg_exit(msg) do{ perror(msg); fprintf(stderr, "file %s line %d\n", __FILE__, __LINE__); exit(EXIT_FAILURE); }while(0) static int setnonblocking(int sockfd) { if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) { return -1; } return 0; } int main(int argc, char *argv[]) { signal_init(); int max_worker = 2; int child = 0; int epollfd = 0; struct sockaddr_in saddr; int sockfd = 0; int nfds = 0; int index = 0; int fd = 0; int acceptfd = 0; struct epoll_event *events; memset(&saddr, 0, sizeof(struct sockaddr_in)); sockfd=open_socket(&saddr); if(sockfd == -1) err_log_exit(); while(!graceful&&!child){ if(max_worker>0){ switch(fork()){ case -1: err_log_exit(); break; case 0: child =1; break; default: printf("child creat\n"); max_worker--; break; } }else{ int status =0; if( -1 != wait(&status)){ //max_worker++; fprintf(stderr, "child quit\n"); } } } if(!child){ fprintf(stderr, "before quit, kill all child\n"); kill(0, SIGINT); sleep(2); return 0; } //child epollfd = server_epoll_create(MAX_FDS+1); if(epollfd == -1) err_log_exit(); if(server_epoll_event_add(epollfd, sockfd) == -1) err_log_exit(); events = (struct epoll_event*)malloc(MAX_FDS*sizeof(struct epoll_event)); memset(events, 0, MAX_FDS*sizeof(struct epoll_event)); /* close stdin and stdout, as they are not needed */ /* move stdin to /dev/null */ if (-1 != (fd = open("/dev/null", O_RDONLY))) { close(STDIN_FILENO); dup2(fd, STDIN_FILENO); close(fd); } /* move stdout to /dev/null */ if (-1 != (fd = open("/dev/null", O_WRONLY))) { close(STDOUT_FILENO); dup2(fd, STDOUT_FILENO); close(fd); } while(child&&!graceful){ nfds = epoll_wait(epollfd, events, MAX_FDS, 500); index = 0; while(index < nfds){ if(events[index].data.fd == sockfd){ acceptfd = accept_client(sockfd, &saddr); //waking herd if(acceptfd == -1){ perror("accept failed\n"); }else{ //accept ok if(server_epoll_event_add(epollfd, acceptfd) == -1) err_log_exit(); } }else if(events[index].data.fd == acceptfd){ // receive data from client // if client close, need avoid TIME_WAIT status if(process_request(acceptfd) == 0){ fprintf(stderr, "client close, close connection and quit listen connect fd\n"); if(server_epoll_event_del(epollfd, acceptfd) == -1) err_log_exit(); close(acceptfd); } }else{ } index++; }; if(nfds == -1){ if (errno == EINTR) continue; else{ err_log_exit(); } } }; return 0; } void server_graceful_set(int g) { if(g>0){ g=1; }else{ g=0; } graceful=g; } int server_graceful_get() { return graceful; } static int open_socket(struct sockaddr_in* paddr) { int sockfd = 0; struct sockaddr_in sockaddress; bzero(&sockaddress, sizeof(sockaddress)); if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) err_log_exit(); sockaddress.sin_family = AF_INET; sockaddress.sin_port = htons(HTTP_PORT); setnonblocking(sockfd); inet_pton(AF_INET, "10.174.8.163", &(sockaddress.sin_addr)); if(bind(sockfd, (struct sockaddr*)(&sockaddress), sizeof(sockaddress)) == -1) err_log_exit(); if(listen(sockfd, BACK_LOG) == -1) err_log_exit(); *paddr = sockaddress; return sockfd; } static int accept_client(int sockfd, struct sockaddr_in* paddr) { socklen_t len = SOCKLEN; int connfd = 0; if(paddr != NULL) { connfd = accept(sockfd, (struct sockaddr*)(paddr), &len); }else { connfd = -1; } return connfd; } static int process_request(int connfd) { char request[1000]; int len = 0; bzero(request, sizeof(request)); len = recv(connfd, request, sizeof(request), 0); if(len >0) fprintf(stderr, "%s\n", request); return len; }
#include <unistd.h> #include <string.h> #include "server_epoll.h" int server_epoll_event_add(int epollfd, int sockfd) { struct epoll_event ep; memset(&ep, 0, sizeof(ep)); ep.events = 0; ep.events |= EPOLLIN; ep.events |= EPOLLOUT; ep.data.fd = sockfd; return epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ep); } int server_epoll_event_del(int epollfd, int sockfd) { struct epoll_event ep; memset(&ep, 0, sizeof(ep)); ep.events = 0; ep.events |= EPOLLIN; ep.events |= EPOLLOUT; ep.data.fd = sockfd; return epoll_ctl(epollfd, EPOLL_CTL_DEL, sockfd, &ep); } int server_epoll_create(int size) { int fd = epoll_create(size); return fd; } int server_epoll_close(int fd) { return close(fd); }