zoukankan      html  css  js  c++  java
  • 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);
    }
  • 相关阅读:
    《大道至简》之五
    String类总结
    《大道至简》之沟通
    程序设计及总结
    《大道至简》之团队
    动手动脑课堂作业7---------
    动手动脑课堂作业7
    动手动脑
    大道至简—现实中的软件工程—思考还是思想
    动手动脑
  • 原文地址:https://www.cnblogs.com/unixshell/p/3518992.html
Copyright © 2011-2022 走看看