简单http_server的C语言实现

阅读更多
主要实现以下几点:

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 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 

// 建立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,"

%s Method Not Implemented

","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,"404 Not Found

404 Not Found


Powered by %s
","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,"Index of %s

Index of %s

  • Parent Directory
  • ",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,"
  • %s/
  • ",ptr->d_name,ptr->d_name); } else { memset(&buf,0,sizeof(buf)); sprintf(buf,"
  • %s
  • ",ptr->d_name,ptr->d_name); } strcat(tmp,buf); } } closedir(dir); memset(&buf,0,sizeof(buf)); sprintf(buf,"%s","
"); 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; }

你可能感兴趣的:(C++,C#,C,D语言,CSS)