webserver<2>

#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
", __FILE__, __LINE__);
    exit(EXIT_FAILURE);
    }while(0)


#define err_msg_exit(msg)
    do{
    perror(msg);
    fprintf(stderr, "file %s line %d
", __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
");
                max_worker--;
              break;
              }
                }else{
              int status =0;
              if( -1 != wait(&status)){
                   //max_worker++;
                   fprintf(stderr, "child quit
");
              }
                }
        }
 
         if(!child){
            fprintf(stderr, "before quit, kill all child
");
            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
");   
              }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
");
                   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
", 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);
}
原文地址:https://www.cnblogs.com/unixshell/p/3824501.html