简单http_server的C语言实现

主要实现以下几点: 

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

2.文件不存在404 

3.目录列表 

4.501 Not Implemented 

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

启动脚本 
Shell代码   收藏代码
  1. #!/bin/sh  
  2.   
  3. ps -ef | grep fasthttp | grep -v grep | awk '{print $2}' | xargs -t -i kill -9 {} >/dev/null  
  4. gcc   fasthttp.c -o fasthttp  
  5. $(pwd)/fasthttp  


以下是源码 

===================================================================================== 
C代码   收藏代码
  1. #include <string.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <netinet/in.h>  
  5. #include <error.h>  
  6. #include <errno.h>  
  7.   
  8. #include <sys/types.h>  
  9. #include <dirent.h>  
  10. #include <sys/socket.h>  
  11. #include <sys/stat.h>  
  12. #include <unistd.h>  
  13. #include <fcntl.h>  
  14.   
  15. // 建立socket 开始侦听 接收连接 接收客户端数据 解析http协议 发送文件数据给客户端  
  16.   
  17. #define HTTP_PORT "2010"  
  18. #define MAX_CONNECTION 10  
  19. #define DOCUMENT_ROOT "www"  
  20. #define LOG_PATH "log/access.log"  
  21.   
  22. void parser(char *s,char res[][255],char host[][255]);  
  23. static char *strtoupper( char *s );  
  24. static long filesize(const char *filename);  
  25. static int file_exists(const char *filename);  
  26. static void mime_content_type( const char *name, char *ret );  
  27. static int WriteLog( const char *message );  
  28. static int is_dir(const char *filename);  
  29.   
  30. static unsigned short g_is_log        = 1;  
  31. static int g_log_fd                    = 0;  
  32.   
  33. int main(void)  
  34. {  
  35.     int server_sock;  
  36.     int client_sock;  
  37.     struct sockaddr_in server_addr;  
  38.     struct sockaddr_in client_addr;  
  39.     struct sockaddr_in sin;  
  40.     struct stat file_stat;  
  41.     pid_t pid;  
  42.     char client_ip[100];  
  43.     char buf[20000];  
  44.     char buf_all[2000];  
  45.     char buf1[2000];  
  46.     char p[3][255];  
  47.     char h[3][255];  
  48.     char tmp[2000];  
  49.     char cwd[1024];  
  50.     char filename[2000];  
  51.     char filepath[2000];  
  52.     int fd,size;  
  53.     int currentConn = 0;  
  54.       
  55.     DIR * dir;  
  56.     struct dirent * ptr;  
  57.       
  58.   
  59.   
  60.     chdir("../");  
  61.       
  62.     if ( (pid = fork()) < 0 )  
  63.     {  
  64.         perror("fork");  
  65.         exit(1);  
  66.     }  
  67.     else if ( pid != 0)  
  68.     {  
  69.         exit(1);  
  70.     }  
  71.       
  72.     if((server_sock = socket(AF_INET,SOCK_STREAM,0)) < 0)  
  73.     {  
  74.         perror("socket");  
  75.         exit(1);  
  76.     }  
  77.       
  78.     memset(&server_addr,0,sizeof(server_addr));  
  79.     server_addr.sin_family = AF_INET;  
  80.     server_addr.sin_port = htons(atoi(HTTP_PORT));  
  81.     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  82.       
  83.     if(bind(server_sock,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)  
  84.     {  
  85.         perror("bind");  
  86.         exit(1);  
  87.     }  
  88.       
  89.     if(listen(server_sock,MAX_CONNECTION) < 0)  
  90.     {  
  91.         perror("listen");  
  92.         exit(1);  
  93.     }  
  94.       
  95.     printf("fasthttp successful created ...\n");  
  96.       
  97.     while(1)  
  98.     {  
  99.         unsigned int clientlen = sizeof(client_addr);  
  100.         if((client_sock = accept(server_sock,(struct sockaddr*)&client_addr,&clientlen)) < 0)  
  101.         {  
  102.             perror("accept");  
  103.             exit(1);  
  104.         }  
  105.           
  106.         if((pid = fork()) == 0)  
  107.         {  
  108.   
  109.             if(read(client_sock,buf,20000) < 0)  
  110.             {  
  111.                 perror("read data from client");  
  112.                 exit(1);  
  113.             }  
  114.               
  115.             parser(buf,p,h);  
  116.               
  117.             if(strcmp(strtoupper(p[0]),"GET") != 0  
  118.                 && strcmp(strtoupper(p[0]),"POST") != 0  
  119.                 && strcmp(strtoupper(p[0]),"HEAD") != 0)  
  120.             {  
  121.                 memset(&buf,0,sizeof(buf));  
  122.                   
  123.                 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");  
  124.                 write(client_sock,buf,strlen(buf));  
  125.                   
  126.                 memset(&buf,0,sizeof(buf));  
  127.                 sprintf(buf,"<h2>%s Method Not Implemented</h2>","501");  
  128.                 write(client_sock,buf,strlen(buf));  
  129.                 close(client_sock);  
  130.                 exit(0);  
  131.             }  
  132.                
  133.             if(strcmp(p[1],"/") == 0)  
  134.             {  
  135.                 memset(&tmp,0,sizeof(tmp));  
  136.                 sprintf(tmp,"%s","index.html");  
  137.                 strcat(p[1],tmp);  
  138.             }  
  139.               
  140.             WriteLog(p[1]);  
  141.             getcwd(filepath, sizeof(filepath));  
  142.             strcat(filepath,"/");  
  143.             strcat(filepath,DOCUMENT_ROOT);  
  144.              strcat(filepath,p[1]);  
  145.   
  146.             if(!file_exists(filepath))  
  147.             {  
  148.                 memset(&buf,0,sizeof(buf));  
  149.                 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");  
  150.                 write(client_sock,buf,strlen(buf));  
  151.                   
  152.                 memset(&buf,0,sizeof(buf));  
  153.                 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");  
  154.                 write(client_sock,buf,strlen(buf));  
  155.                 close(client_sock);  
  156.                   
  157.                 memset(&buf,0,sizeof(buf));  
  158.                 sprintf(buf,"404 Not Found\t%s\n",filepath);  
  159.                 WriteLog(buf);  
  160.                   
  161.                 exit(0);  
  162.             }  
  163.               
  164.             if(access(filepath,R_OK) < 0)  
  165.             {  
  166.                 memset(&buf,0,sizeof(buf));  
  167.                 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");  
  168.                 write(client_sock,buf,strlen(buf));  
  169.                 close(client_sock);  
  170.                 exit(0);  
  171.             }  
  172.               
  173.              /** 目录列表 **/  
  174.              if(is_dir(filepath))  
  175.              {  
  176.                 memset(&tmp,0,sizeof(tmp));  
  177.                 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);  
  178.                 strcat(buf,tmp);  
  179.   
  180.                  if((dir = opendir(filepath)) != NULL)  
  181.                  {  
  182.                      while((ptr = readdir(dir)) != NULL)  
  183.                      {  
  184.                            
  185.                          if(strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0)  
  186.                          {  
  187.                              continue;      
  188.                          }  
  189.                            
  190.                          memset(&buf,0,sizeof(buf));  
  191.                          sprintf(buf,"%s/%s",filepath,ptr->d_name);  
  192.                           
  193.                         if(is_dir(buf))  
  194.                         {  
  195.                             memset(&buf,0,sizeof(buf));  
  196.                             sprintf(buf,"<li><a href=\"%s/\"> %s/</a></li>",ptr->d_name,ptr->d_name);  
  197.                         }  
  198.                         else  
  199.                         {  
  200.                             memset(&buf,0,sizeof(buf));  
  201.                             sprintf(buf,"<li><a href=\"%s\"> %s</a></li>",ptr->d_name,ptr->d_name);      
  202.                         }  
  203.                         strcat(tmp,buf);  
  204.                      }  
  205.                  }  
  206.                  closedir(dir);  
  207.   
  208.                  memset(&buf,0,sizeof(buf));  
  209.                 sprintf(buf,"%s","</ul>");  
  210.                 strcat(tmp,buf);  
  211.                   
  212.                 memset(&buf,0,sizeof(buf));  
  213.                 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));  
  214.                 write(client_sock,buf,strlen(buf));  
  215.               
  216.                 write(client_sock,tmp,strlen(tmp));  
  217.                 close(client_sock);  
  218.              }  
  219.                
  220.             memset(&tmp,0,sizeof(tmp));  
  221.             mime_content_type(filepath,tmp);  
  222.               
  223.             memset(&buf,0,sizeof(buf));  
  224.             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);  
  225.             write(client_sock,buf,strlen(buf));  
  226.               
  227.               
  228.               
  229.             memset(&buf,0,sizeof(buf));  
  230.             fd = open(filepath,O_RDONLY);  
  231.             read(fd,buf,filesize(filepath));  
  232.             close(fd);  
  233.               
  234.             write(client_sock,buf,filesize(filepath));  
  235.             close(client_sock);  
  236.               
  237.             memset(&buf,0,sizeof(buf));  
  238.             sprintf(buf,"200 OK\t%s\t%d\n",filepath,filesize(filepath));  
  239.             WriteLog(buf);  
  240.               
  241.             exit(0);  
  242.         }  
  243.         else  
  244.         {  
  245.             wait(NULL);  
  246.         }  
  247.           
  248.         close(client_sock);  
  249.     }  
  250.       
  251.       
  252. }  
  253.   
  254. void parser(char *s,char res[][255],char host[][255])  
  255. {  
  256.     int i,j = 0;  
  257.     int n;  
  258.     char hosts[255];  
  259.   
  260.     for (i = 0;s[i] != '\r';i++)        /* obtain the first line in http protocol head */  
  261.         ;  
  262.     s[i] = '\0';  
  263.     n=i++;  
  264.       
  265.     for (i = 0,j = 0;i < 3;i++,j++)        /* divide the protocol head in blank */  
  266.     {  
  267.         strcpy(res[j],strsep(&s," "));  
  268.     }  
  269.       
  270.     for(i=n;s[i] != '\r';i++)  
  271.     {  
  272.         strcat(hosts,s[i]);  
  273.     }  
  274.       
  275.     for (i = 0,j = 0;i < 3;i++,j++)        /* divide the protocol head in blank */  
  276.     {  
  277.         strcpy(host[j],strsep(&hosts,":"));  
  278.     }  
  279.       
  280. }  
  281.   
  282. /** 
  283.  * strtoupper - string to upper 
  284.  * 
  285.  */  
  286. static char *strtoupper( char *s )  
  287. {  
  288.     int i, len = sizeof(s);  
  289.     for( i = 0; i < len; i++ )  
  290.     {  
  291.         s[i] = ( s[i] >= 'a' && s[i] <= 'z' ? s[i] + 'A' - 'a' : s[i] );  
  292.     }  
  293.       
  294.     return(s);  
  295. }  
  296.   
  297. /** 
  298.  *  filesize - get file size 
  299.  */  
  300. static long filesize(const char *filename)  
  301. {  
  302.     struct stat buf;  
  303.     if (!stat(filename, &buf))  
  304.     {  
  305.         return buf.st_size;  
  306.     }  
  307.     return 0;  
  308. }  
  309.   
  310. /** 
  311.  * file_exists - check file is exist 
  312.  */  
  313. static int file_exists(const char *filename)  
  314. {  
  315.     struct stat buf;  
  316.       
  317.     if (stat(filename, &buf) < 0)  
  318.     {  
  319.         if (errno == ENOENT)  
  320.         {  
  321.             return 0;  
  322.         }  
  323.     }  
  324.     return 1;  
  325. }  
  326.   
  327. /** 
  328.  * Get MIME type header 
  329.  * 
  330.  */  
  331. static void mime_content_type( const char *name, char *ret ){  
  332.     char *dot, *buf;  
  333.   
  334.     dot = strrchr(name, '.');  
  335.   
  336.     /* Text */  
  337.     if ( strcmp(dot, ".txt") == 0 ){  
  338.         buf = "text/plain";  
  339.     } else if ( strcmp( dot, ".css" ) == 0 ){  
  340.         buf = "text/css";  
  341.     } else if ( strcmp( dot, ".js" ) == 0 ){  
  342.         buf = "text/javascript";  
  343.     } else if ( strcmp(dot, ".xml") == 0 || strcmp(dot, ".xsl") == 0 ){  
  344.         buf = "text/xml";  
  345.     } else if ( strcmp(dot, ".xhtm") == 0 || strcmp(dot, ".xhtml") == 0 || strcmp(dot, ".xht") == 0 ){  
  346.         buf = "application/xhtml+xml";  
  347.     } else if ( strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0 || strcmp(dot, ".shtml") == 0 || strcmp(dot, ".hts") == 0 ){  
  348.         buf = "text/html";  
  349.   
  350.     /* Images */  
  351.     } else if ( strcmp( dot, ".gif" ) == 0 ){  
  352.         buf = "image/gif";  
  353.     } else if ( strcmp( dot, ".png" ) == 0 ){  
  354.         buf = "image/png";  
  355.     } else if ( strcmp( dot, ".bmp" ) == 0 ){  
  356.         buf = "application/x-MS-bmp";  
  357.     } else if ( strcmp( dot, ".jpg" ) == 0 || strcmp( dot, ".jpeg" ) == 0 || strcmp( dot, ".jpe" ) == 0 || strcmp( dot, ".jpz" ) == 0 ){  
  358.         buf = "image/jpeg";  
  359.   
  360.     /* Audio & Video */  
  361.     } else if ( strcmp( dot, ".wav" ) == 0 ){  
  362.         buf = "audio/wav";  
  363.     } else if ( strcmp( dot, ".wma" ) == 0 ){  
  364.         buf = "audio/x-ms-wma";  
  365.     } else if ( strcmp( dot, ".wmv" ) == 0 ){  
  366.         buf = "audio/x-ms-wmv";  
  367.     } else if ( strcmp( dot, ".au" ) == 0 || strcmp( dot, ".snd" ) == 0 ){  
  368.         buf = "audio/basic";  
  369.     } else if ( strcmp( dot, ".midi" ) == 0 || strcmp( dot, ".mid" ) == 0 ){  
  370.         buf = "audio/midi";  
  371.     } else if ( strcmp( dot, ".mp3" ) == 0 || strcmp( dot, ".mp2" ) == 0 ){  
  372.         buf = "audio/x-mpeg";  
  373.     } else if ( strcmp( dot, ".rm" ) == 0  || strcmp( dot, ".rmvb" ) == 0 || strcmp( dot, ".rmm" ) == 0 ){  
  374.         buf = "audio/x-pn-realaudio";  
  375.     } else if ( strcmp( dot, ".avi" ) == 0 ){  
  376.         buf = "video/x-msvideo";  
  377.     } else if ( strcmp( dot, ".3gp" ) == 0 ){  
  378.         buf = "video/3gpp";  
  379.     } else if ( strcmp( dot, ".mov" ) == 0 ){  
  380.         buf = "video/quicktime";  
  381.     } else if ( strcmp( dot, ".wmx" ) == 0 ){  
  382.         buf = "video/x-ms-wmx";  
  383.     } else if ( strcmp( dot, ".asf" ) == 0  || strcmp( dot, ".asx" ) == 0 ){  
  384.         buf = "video/x-ms-asf";  
  385.     } else if ( strcmp( dot, ".mp4" ) == 0 || strcmp( dot, ".mpg4" ) == 0 ){  
  386.         buf = "video/mp4";  
  387.     } else if ( strcmp( dot, ".mpe" ) == 0  || strcmp( dot, ".mpeg" ) == 0 || strcmp( dot, ".mpg" ) == 0 || strcmp( dot, ".mpga" ) == 0 ){  
  388.         buf = "video/mpeg";  
  389.   
  390.     /* Documents */  
  391.     } else if ( strcmp( dot, ".pdf" ) == 0 ){  
  392.         buf = "application/pdf";  
  393.     } else if ( strcmp( dot, ".rtf" ) == 0 ){  
  394.         buf = "application/rtf";  
  395.     } else if ( strcmp( dot, ".doc" ) == 0  || strcmp( dot, ".dot" ) == 0 ){  
  396.         buf = "application/msword";  
  397.     } else if ( strcmp( dot, ".xls" ) == 0  || strcmp( dot, ".xla" ) == 0 ){  
  398.         buf = "application/msexcel";  
  399.     } else if ( strcmp( dot, ".hlp" ) == 0  || strcmp( dot, ".chm" ) == 0 ){  
  400.         buf = "application/mshelp";  
  401.     } else if ( strcmp( dot, ".swf" ) == 0  || strcmp( dot, ".swfl" ) == 0 || strcmp( dot, ".cab" ) == 0 ){  
  402.         buf = "application/x-shockwave-flash";  
  403.     } else if ( strcmp( dot, ".ppt" ) == 0  || strcmp( dot, ".ppz" ) == 0 || strcmp( dot, ".pps" ) == 0 || strcmp( dot, ".pot" ) == 0 ){  
  404.         buf = "application/mspowerpoint";  
  405.   
  406.     /* Binary & Packages */  
  407.     } else if ( strcmp( dot, ".zip" ) == 0 ){  
  408.         buf = "application/zip";  
  409.     } else if ( strcmp( dot, ".rar" ) == 0 ){  
  410.         buf = "application/x-rar-compressed";  
  411.     } else if ( strcmp( dot, ".gz" ) == 0 ){  
  412.         buf = "application/x-gzip";  
  413.     } else if ( strcmp( dot, ".jar" ) == 0 ){  
  414.         buf = "application/java-archive";  
  415.     } else if ( strcmp( dot, ".tgz" ) == 0  || strcmp( dot, ".tar" ) == 0 ){  
  416.         buf = "application/x-tar";  
  417.     } else {  
  418.         buf = "application/octet-stream";  
  419.     }  
  420.     strcpy(ret, buf);  
  421. }  
  422.   
  423. /** 
  424.  * Log message 
  425.  * 
  426.  */  
  427. static int WriteLog( const char *message )  
  428. {  
  429.     if ( !g_is_log )  
  430.     {  
  431.         fprintf(stderr, "%s", message);  
  432.         return 0;  
  433.     }  
  434.     if ( g_log_fd == 0 )  
  435.     {  
  436.         char g_log_path[2000];  
  437.         getcwd(g_log_path, sizeof(g_log_path));  
  438.         strcat(g_log_path,"/");  
  439.         strcat(g_log_path,LOG_PATH);  
  440.           
  441.         if ( (g_log_fd = open(g_log_path, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1 )  
  442.         {  
  443.             perror("open log file error");  
  444.             return -1;  
  445.         }  
  446.     }  
  447.       
  448.     if (write(g_log_fd, message, strlen(message)) == -1)  
  449.     {  
  450.         perror("write log error");  
  451.         return -1;  
  452.     }  
  453.   
  454.     return 0;  
  455. }  
  456.   
  457. /** 
  458.  * is_dir - check file is directory 
  459.  * 
  460.  */  
  461. static int is_dir(const char *filename){  
  462.     struct stat buf;  
  463.     if ( stat(filename, &buf) < 0 ){  
  464.         return -1;  
  465.     }  
  466.     if (S_ISDIR(buf.st_mode)){  
  467.         return 1;  
  468.     }  
  469.     return 0;  

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