http server v0.1_http_server.c

/****************************************************************
    filename: http_server.c
    author:   xxxx
    function: Main file of http server
          Impliment the response of Get and Post mehtods
   
        history:
        created by xxxx date: 2014.01.03                    
       
*****************************************************************/


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "mime.h"
#include "http_common.h"
#include "http_webapp.h"
// __DEBUG__ is debug tag

#define BACK_LOG    50
#define SOCKLEN        sizeof(struct sockaddr_in)

//
static int open_socket(struct sockaddr_in*);
static int accept_client(int sockfd, struct sockaddr_in* paddr);
static void wait_child();

static void write_response_body(int connfd, char* uri, int filesize);
void process_request(int connfd);

int main()
{
//    char type[MAX_FILE_TYPE_LEN]="";
//    get_mime_type("test.html",type);

    int sockfd = 0;
    int connfd = 0;    
    struct  sockaddr_in     sockaddress;
    pid_t chld = 0;
    //struct  sigaction    sa;
    
    bzero(&sockaddress, sizeof(struct sockaddr_in));
    signal(SIGCHLD, wait_child);
    //open sock
    if((sockfd=open_socket(&sockaddress)) == -1)
    {
        perror("open socket failed");
        return -1;
    }    

    //accept client connection
    while(1)
    {
        connfd = accept_client(sockfd, &sockaddress);

        #if __DEBUG__
        printf("client accept [%d]
 ", connfd);        
        #endif

        if((chld = fork()) > 0)
        {    //root
            close(connfd);
            continue;
        }else if(chld == 0)
        {    //childi
            process_request(connfd);
            close(sockfd);
            exit(0);
        }
        
    }
    
    
    return 0;
}

/*---------------------------------------------------------------

functionname: open_socket
param:    NA
return:    return sockfd on success, -1 on fail
author: xxxx

----------------------------------------------------------------*/
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)
        return -1;
    
    sockaddress.sin_family = AF_INET;
    sockaddress.sin_port   = htons(HTTP_PORT);    
    
    inet_pton(AF_INET, "10.174.8.163", &(sockaddress.sin_addr));
    
    if(bind(sockfd, (struct sockaddr*)(&sockaddress), sizeof(sockaddress)) == -1)
        return -1;
    
    if(listen(sockfd, BACK_LOG) == -1)
        return -1;
    
    *paddr = sockaddress;
    return sockfd;
}


/*---------------------------------------------------------------

functionname: accept_client
param:    NA
return:    return connfd on success, -1 on fail
author: xxxx

----------------------------------------------------------------*/

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;    
}

/*----------------------------------------------------------------

functionname: wait_child_exit
param:  NA
return: NA
author: xxxx
    
    TO KILL CHILD PROCESS, avoid ZOOBIE

-----------------------------------------------------------------*/

static void wait_child()
{
    int status = 0;
    while(waitpid(-1, &status, WNOHANG) > 0)
    {
        #if 0
        printf("child process exit
");
        #endif
    }
    return;
}

/*-----------------------------------------------------------------

functionname: process_request
param:  NA
return: NA
author: xxxx
    
    http request process
    history:    
    create by xxxx, 2014.1.08, add simple abilities
            
-----------------------------------------------------------------*/

void process_request(int connfd)
{
    char request[MAX_REQUEST_LEN];
    STR_REQUEST strreq;    
    EN_MIME_TYPE  type     = MIME_ELSE;
    EN_REP_STATUS status   = HTTP_END;    
    STR_RESP      response;
    long           filesize = 0;
    FILE*          fstream  = NULL;

    bzero(&strreq, sizeof(STR_REQUEST));
    bzero(request, sizeof(request));
    bzero(&response, sizeof(STR_RESP));

    if(recv(connfd, request, sizeof(request), 0) >0)
    {
        
        if(parse_request(request, &strreq) ==0)
        {
            #if __DEBUG__
            printf("request:%s
", request);
            #endif
                
            get_mime_type(strreq.URI,&type);
    
            // file does not exist 404
            if(file_exist(strreq.URI) == -1)        
            {
                status = HTTP_NOT_FOUND;    
                fstream = fopen(HTML_404, "rb");
            }else
            {
                status = HTTP_OK;
                fstream = fopen(strreq.URI, "rb");
            }
            
            filesize=get_file_size(fstream);        
            #if __DEBUG__
            printf("request file size = [%ld]
", filesize);
            #endif
            //response.data = (void*)malloc(filesize);
            //bzero(response.data, filesize);
            get_response_head(status,type,response.head,(int)filesize);
            #if __DEBUG__
            printf("response head = [%s]", response.head);
            #endif
            //if(get_response_body(type, response.data, strreq.URI, filesize) == -1)
            //    perror("fill response body failed");
            
            #if __DEBUG__
            //printf("response body = [%s]
", (char*)(response.data));
            #endif    
            fclose(fstream);
            send(connfd, response.head, strlen(response.head), 0);
            write_response_body(connfd, strreq.URI, (int)filesize);
            shutdown(connfd, SHUT_RD);
            close(connfd);
        }
    }
}

static void write_response_body(int connfd, char* uri, int filesize)
{
    int fd =0;
    void*     bodybuf = NULL;
    fd = open(uri, O_RDONLY, 0);
    bodybuf = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);     
        send(connfd, bodybuf, filesize, 0);
    munmap(bodybuf, filesize);
}
原文地址:https://www.cnblogs.com/unixshell/p/3518992.html