简单http_server的C语言实现

       一直未能理解网络编程的精髓,TCP/IP协议,HTTP协议等,昨天上班的时候就突然想搞个,不想看JAVA的,因为JAVA的很多都用到写好的HttpRequest类(不知道这样理解是否有误),还是喜欢C语言。百度之,抄一HttpServer如下,上班的时候也有其他事情的,所以未能完成。一下代码尚未完全实践过。到实践了再更新,先搬过来哈

主要实现以下几点: 


1.静态文件访问,包括jpg、html、css等 

2.文件不存在404 

3.目录列表 

4.501 Not Implemented 

============================================================================= 

#!/bin/sh  
  
ps -ef | grep fasthttp | grep -v grep | awk '{print $2}' | xargs -t -i kill -9 {} >/dev/null  
gcc   fasthttp.c -o fasthttp  
$(pwd)/fasthttp  

以下是源码 

=====================================================================================

#include <string.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <netinet/in.h>  
#include <error.h>  
#include <errno.h>  
  
#include <sys/types.h>  
#include <dirent.h>  
#include <sys/socket.h>  
#include <sys/stat.h>  
#include <unistd.h>  
#include <fcntl.h>  
  
// 建立socket 开始侦听 接收连接 接收客户端数据 解析http协议 发送文件数据给客户端  
  
#define HTTP_PORT "2010"  
#define MAX_CONNECTION 10  
#define DOCUMENT_ROOT "www"  
#define LOG_PATH "log/access.log"  
  
void parser(char *s,char res[][255],char host[][255]);  
static char *strtoupper( char *s );  
static long filesize(const char *filename);  
static int file_exists(const char *filename);  
static void mime_content_type( const char *name, char *ret );  
static int WriteLog( const char *message );  
static int is_dir(const char *filename);  
  
static unsigned short g_is_log        = 1;  
static int g_log_fd                    = 0;  
  
int main(void)  
{  
    int server_sock;  
    int client_sock;  
    struct sockaddr_in server_addr;  
    struct sockaddr_in client_addr;  
    struct sockaddr_in sin;  
    struct stat file_stat;  
    pid_t pid;  
    char client_ip[100];  
    char buf[20000];  
    char buf_all[2000];  
    char buf1[2000];  
    char p[3][255];  
    char h[3][255];  
    char tmp[2000];  
    char cwd[1024];  
    char filename[2000];  
    char filepath[2000];  
    int fd,size;  
    int currentConn = 0;  
      
    DIR * dir;  
    struct dirent * ptr;  
      
  
  
    chdir("../");  
      
    if ( (pid = fork()) < 0 )  
    {  
        perror("fork");  
        exit(1);  
    }  
    else if ( pid != 0)  
    {  
        exit(1);  
    }  
      
    if((server_sock = socket(AF_INET,SOCK_STREAM,0)) < 0)  
    {  
        perror("socket");  
        exit(1);  
    }  
      
    memset(&server_addr,0,sizeof(server_addr));  
    server_addr.sin_family = AF_INET;  
    server_addr.sin_port = htons(atoi(HTTP_PORT));  
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
      
    if(bind(server_sock,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)  
    {  
        perror("bind");  
        exit(1);  
    }  
      
    if(listen(server_sock,MAX_CONNECTION) < 0)  
    {  
        perror("listen");  
        exit(1);  
    }  
      
    printf("fasthttp successful created ...\n");  
      
    while(1)  
    {  
        unsigned int clientlen = sizeof(client_addr);  
        if((client_sock = accept(server_sock,(struct sockaddr*)&client_addr,&clientlen)) < 0)  
        {  
            perror("accept");  
            exit(1);  
        }  
          
        if((pid = fork()) == 0)  
        {  
  
            if(read(client_sock,buf,20000) < 0)  
            {  
                perror("read data from client");  
                exit(1);  
            }  
              
            parser(buf,p,h);  
              
            if(strcmp(strtoupper(p[0]),"GET") != 0  
                && strcmp(strtoupper(p[0]),"POST") != 0  
                && strcmp(strtoupper(p[0]),"HEAD") != 0)  
            {  
                memset(&buf,0,sizeof(buf));  
                  
                sprintf(buf, "HTTP/1.1 501 Not Implemented\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length:    1489\r\nAccept-Ranges: bytes\r\nConnection: close\r\n\r\n", "Apache");  
                write(client_sock,buf,strlen(buf));  
                  
                memset(&buf,0,sizeof(buf));  
                sprintf(buf,"<h2>%s Method Not Implemented</h2>","501");  
                write(client_sock,buf,strlen(buf));  
                close(client_sock);  
                exit(0);  
            }  
               
            if(strcmp(p[1],"/") == 0)  
            {  
                memset(&tmp,0,sizeof(tmp));  
                sprintf(tmp,"%s","index.html");  
                strcat(p[1],tmp);  
            }  
              
            WriteLog(p[1]);  
            getcwd(filepath, sizeof(filepath));  
            strcat(filepath,"/");  
            strcat(filepath,DOCUMENT_ROOT);  
             strcat(filepath,p[1]);  
  
            if(!file_exists(filepath))  
            {  
                memset(&buf,0,sizeof(buf));  
                sprintf(buf, "HTTP/1.1 404 Not Found\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length:    257271\r\nConnection: close\r\n\r\n", "Apache");  
                write(client_sock,buf,strlen(buf));  
                  
                memset(&buf,0,sizeof(buf));  
                sprintf(buf,"<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr><center>Powered by %s</center></body></html>","fasthttp");  
                write(client_sock,buf,strlen(buf));  
                close(client_sock);  
                  
                memset(&buf,0,sizeof(buf));  
                sprintf(buf,"404 Not Found\t%s\n",filepath);  
                WriteLog(buf);  
                  
                exit(0);  
            }  
              
            if(access(filepath,R_OK) < 0)  
            {  
                memset(&buf,0,sizeof(buf));  
                sprintf(buf, "HTTP/1.1 403 Forbidden\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length:    25727\r\nConnection: close\r\n\r\n", "Apache");  
                write(client_sock,buf,strlen(buf));  
                close(client_sock);  
                exit(0);  
            }  
              
             /** 目录列表 **/  
             if(is_dir(filepath))  
             {  
                memset(&tmp,0,sizeof(tmp));  
                sprintf(tmp,"<html><head><title>Index of %s</title></head><body><h1>Index of %s</h1><ul><li><a href=\"/\"> Parent Directory</a></li>",filepath,filepath);  
                strcat(buf,tmp);  
  
                 if((dir = opendir(filepath)) != NULL)  
                 {  
                     while((ptr = readdir(dir)) != NULL)  
                     {  
                           
                         if(strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0)  
                         {  
                             continue;      
                         }  
                           
                         memset(&buf,0,sizeof(buf));  
                         sprintf(buf,"%s/%s",filepath,ptr->d_name);  
                          
                        if(is_dir(buf))  
                        {  
                            memset(&buf,0,sizeof(buf));  
                            sprintf(buf,"<li><a href=\"%s/\"> %s/</a></li>",ptr->d_name,ptr->d_name);  
                        }  
                        else  
                        {  
                            memset(&buf,0,sizeof(buf));  
                            sprintf(buf,"<li><a href=\"%s\"> %s</a></li>",ptr->d_name,ptr->d_name);      
                        }  
                        strcat(tmp,buf);  
                     }  
                 }  
                 closedir(dir);  
  
                 memset(&buf,0,sizeof(buf));  
                sprintf(buf,"%s","</ul>");  
                strcat(tmp,buf);  
                  
                memset(&buf,0,sizeof(buf));  
                sprintf(buf, "HTTP/1.1 200 OK\r\nServer: fasthttp\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length:    %d\r\nConnection: close\r\n\r\n", strlen(tmp));  
                write(client_sock,buf,strlen(buf));  
              
                write(client_sock,tmp,strlen(tmp));  
                close(client_sock);  
             }  
               
            memset(&tmp,0,sizeof(tmp));  
            mime_content_type(filepath,tmp);  
              
            memset(&buf,0,sizeof(buf));  
            sprintf(buf, "HTTP/1.1 200 OK\r\nServer: %s\r\nContent-Type: %s\r\nContent-Length:    25727\r\nConnection: close\r\n\r\n", "Apache",tmp);  
            write(client_sock,buf,strlen(buf));  
              
              
              
            memset(&buf,0,sizeof(buf));  
            fd = open(filepath,O_RDONLY);  
            read(fd,buf,filesize(filepath));  
            close(fd);  
              
            write(client_sock,buf,filesize(filepath));  
            close(client_sock);  
              
            memset(&buf,0,sizeof(buf));  
            sprintf(buf,"200 OK\t%s\t%d\n",filepath,filesize(filepath));  
            WriteLog(buf);  
              
            exit(0);  
        }  
        else  
        {  
            wait(NULL);  
        }  
          
        close(client_sock);  
    }  
      
      
}  
  
void parser(char *s,char res[][255],char host[][255])  
{  
    int i,j = 0;  
    int n;  
    char hosts[255];  
  
    for (i = 0;s[i] != '\r';i++)        /* obtain the first line in http protocol head */  
        ;  
    s[i] = '\0';  
    n=i++;  
      
    for (i = 0,j = 0;i < 3;i++,j++)        /* divide the protocol head in blank */  
    {  
        strcpy(res[j],strsep(&s," "));  
    }  
      
    for(i=n;s[i] != '\r';i++)  
    {  
        strcat(hosts,s[i]);  
    }  
      
    for (i = 0,j = 0;i < 3;i++,j++)        /* divide the protocol head in blank */  
    {  
        strcpy(host[j],strsep(&hosts,":"));  
    }  
      
}  
  
/** 
 * strtoupper - string to upper 
 * 
 */  
static char *strtoupper( char *s )  
{  
    int i, len = sizeof(s);  
    for( i = 0; i < len; i++ )  
    {  
        s[i] = ( s[i] >= 'a' && s[i] <= 'z' ? s[i] + 'A' - 'a' : s[i] );  
    }  
      
    return(s);  
}  
  
/** 
 *  filesize - get file size 
 */  
static long filesize(const char *filename)  
{  
    struct stat buf;  
    if (!stat(filename, &buf))  
    {  
        return buf.st_size;  
    }  
    return 0;  
}  
  
/** 
 * file_exists - check file is exist 
 */  
static int file_exists(const char *filename)  
{  
    struct stat buf;  
      
    if (stat(filename, &buf) < 0)  
    {  
        if (errno == ENOENT)  
        {  
            return 0;  
        }  
    }  
    return 1;  
}  
  
/** 
 * Get MIME type header 
 * 
 */  
static void mime_content_type( const char *name, char *ret ){  
    char *dot, *buf;  
  
    dot = strrchr(name, '.');  
  
    /* Text */  
    if ( strcmp(dot, ".txt") == 0 ){  
        buf = "text/plain";  
    } else if ( strcmp( dot, ".css" ) == 0 ){  
        buf = "text/css";  
    } else if ( strcmp( dot, ".js" ) == 0 ){  
        buf = "text/javascript";  
    } else if ( strcmp(dot, ".xml") == 0 || strcmp(dot, ".xsl") == 0 ){  
        buf = "text/xml";  
    } else if ( strcmp(dot, ".xhtm") == 0 || strcmp(dot, ".xhtml") == 0 || strcmp(dot, ".xht") == 0 ){  
        buf = "application/xhtml+xml";  
    } else if ( strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0 || strcmp(dot, ".shtml") == 0 || strcmp(dot, ".hts") == 0 ){  
        buf = "text/html";  
  
    /* Images */  
    } else if ( strcmp( dot, ".gif" ) == 0 ){  
        buf = "image/gif";  
    } else if ( strcmp( dot, ".png" ) == 0 ){  
        buf = "image/png";  
    } else if ( strcmp( dot, ".bmp" ) == 0 ){  
        buf = "application/x-MS-bmp";  
    } else if ( strcmp( dot, ".jpg" ) == 0 || strcmp( dot, ".jpeg" ) == 0 || strcmp( dot, ".jpe" ) == 0 || strcmp( dot, ".jpz" ) == 0 ){  
        buf = "image/jpeg";  
  
    /* Audio & Video */  
    } else if ( strcmp( dot, ".wav" ) == 0 ){  
        buf = "audio/wav";  
    } else if ( strcmp( dot, ".wma" ) == 0 ){  
        buf = "audio/x-ms-wma";  
    } else if ( strcmp( dot, ".wmv" ) == 0 ){  
        buf = "audio/x-ms-wmv";  
    } else if ( strcmp( dot, ".au" ) == 0 || strcmp( dot, ".snd" ) == 0 ){  
        buf = "audio/basic";  
    } else if ( strcmp( dot, ".midi" ) == 0 || strcmp( dot, ".mid" ) == 0 ){  
        buf = "audio/midi";  
    } else if ( strcmp( dot, ".mp3" ) == 0 || strcmp( dot, ".mp2" ) == 0 ){  
        buf = "audio/x-mpeg";  
    } else if ( strcmp( dot, ".rm" ) == 0  || strcmp( dot, ".rmvb" ) == 0 || strcmp( dot, ".rmm" ) == 0 ){  
        buf = "audio/x-pn-realaudio";  
    } else if ( strcmp( dot, ".avi" ) == 0 ){  
        buf = "video/x-msvideo";  
    } else if ( strcmp( dot, ".3gp" ) == 0 ){  
        buf = "video/3gpp";  
    } else if ( strcmp( dot, ".mov" ) == 0 ){  
        buf = "video/quicktime";  
    } else if ( strcmp( dot, ".wmx" ) == 0 ){  
        buf = "video/x-ms-wmx";  
    } else if ( strcmp( dot, ".asf" ) == 0  || strcmp( dot, ".asx" ) == 0 ){  
        buf = "video/x-ms-asf";  
    } else if ( strcmp( dot, ".mp4" ) == 0 || strcmp( dot, ".mpg4" ) == 0 ){  
        buf = "video/mp4";  
    } else if ( strcmp( dot, ".mpe" ) == 0  || strcmp( dot, ".mpeg" ) == 0 || strcmp( dot, ".mpg" ) == 0 || strcmp( dot, ".mpga" ) == 0 ){  
        buf = "video/mpeg";  
  
    /* Documents */  
    } else if ( strcmp( dot, ".pdf" ) == 0 ){  
        buf = "application/pdf";  
    } else if ( strcmp( dot, ".rtf" ) == 0 ){  
        buf = "application/rtf";  
    } else if ( strcmp( dot, ".doc" ) == 0  || strcmp( dot, ".dot" ) == 0 ){  
        buf = "application/msword";  
    } else if ( strcmp( dot, ".xls" ) == 0  || strcmp( dot, ".xla" ) == 0 ){  
        buf = "application/msexcel";  
    } else if ( strcmp( dot, ".hlp" ) == 0  || strcmp( dot, ".chm" ) == 0 ){  
        buf = "application/mshelp";  
    } else if ( strcmp( dot, ".swf" ) == 0  || strcmp( dot, ".swfl" ) == 0 || strcmp( dot, ".cab" ) == 0 ){  
        buf = "application/x-shockwave-flash";  
    } else if ( strcmp( dot, ".ppt" ) == 0  || strcmp( dot, ".ppz" ) == 0 || strcmp( dot, ".pps" ) == 0 || strcmp( dot, ".pot" ) == 0 ){  
        buf = "application/mspowerpoint";  
  
    /* Binary & Packages */  
    } else if ( strcmp( dot, ".zip" ) == 0 ){  
        buf = "application/zip";  
    } else if ( strcmp( dot, ".rar" ) == 0 ){  
        buf = "application/x-rar-compressed";  
    } else if ( strcmp( dot, ".gz" ) == 0 ){  
        buf = "application/x-gzip";  
    } else if ( strcmp( dot, ".jar" ) == 0 ){  
        buf = "application/java-archive";  
    } else if ( strcmp( dot, ".tgz" ) == 0  || strcmp( dot, ".tar" ) == 0 ){  
        buf = "application/x-tar";  
    } else {  
        buf = "application/octet-stream";  
    }  
    strcpy(ret, buf);  
}  
  
/** 
 * Log message 
 * 
 */  
static int WriteLog( const char *message )  
{  
    if ( !g_is_log )  
    {  
        fprintf(stderr, "%s", message);  
        return 0;  
    }  
    if ( g_log_fd == 0 )  
    {  
        char g_log_path[2000];  
        getcwd(g_log_path, sizeof(g_log_path));  
        strcat(g_log_path,"/");  
        strcat(g_log_path,LOG_PATH);  
          
        if ( (g_log_fd = open(g_log_path, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1 )  
        {  
            perror("open log file error");  
            return -1;  
        }  
    }  
      
    if (write(g_log_fd, message, strlen(message)) == -1)  
    {  
        perror("write log error");  
        return -1;  
    }  
  
    return 0;  
}  
  
/** 
 * is_dir - check file is directory 
 * 
 */  
static int is_dir(const char *filename){  
    struct stat buf;  
    if ( stat(filename, &buf) < 0 ){  
        return -1;  
    }  
    if (S_ISDIR(buf.st_mode)){  
        return 1;  
    }  
    return 0;  
}  


你可能感兴趣的:(简单http_server的C语言实现)