首页 > 代码库 > Linux_C socket 服务器(cat ,execl功能)

Linux_C socket 服务器(cat ,execl功能)

客户端和web服务器交互的基本结构如下:

  (1)客户端发送请求

            GET filename HTTP/version

     可选参数

     空行

 

 (2)服务器发送应答

             HTTP/version status-code status-message

             附加信息

             空行

              内容

 

webserv.c

  1 /* webserv.c    a minimal web server (version 0.2)  2  * usage : webserv portnumber  3  */  4 #include <stdio.h>  5 #include <sys/types.h>  6 #include <sys/socket.h>  7 #include <string.h>  8 #include <sys/stat.h>  9 #include <netinet/in.h> 10 #include <netdb.h> 11  12 int make_server_socket(int); 13  14 int main(int argc, char* argv[]) { 15   int sock, fd; 16   FILE * fpin; 17   char request[BUFSIZ]; 18    19   if(argc==1) { 20     fprintf(stderr , "usage :webserv portnum.\n"); 21     exit(1); 22   } 23   sock=make_server_socket(atoi(argv[1])); 24   if(sock==-1) 25     exit(2); 26   while(1) { 27     /* take a call and buffer it */ 28     fd=accept(sock, NULL, NULL); 29     fpin=fdopen(fd, "r"); 30     /* read request */ 31     fgets(request, BUFSIZ, fpin); 32     printf("get a call ; request = %s", request); 33     read_til_crnl(fpin); 34     /* do what client asks */ 35     process_rq(request, fd); 36      37     fclose(fpin); 38   } 39   return 0; 40 } 41  42 int make_server_socket(int portnum) { 43   int sock; 44   struct sockaddr_in saddr; 45   struct hostent *hp; 46   char hostname[BUFSIZ]; 47    48   sock=socket(PF_INET, SOCK_STREAM, 0); 49   if(sock==-1) 50     return -1; 51    52   gethostname(hostname, BUFSIZ); 53   hp=gethostbyname(hostname); 54   bzero(&saddr, sizeof(saddr)); 55   bcopy((void*)hp->h_addr, (void*)&saddr.sin_addr, hp->h_length); 56   saddr.sin_port=htons(portnum); 57   saddr.sin_family=AF_INET; 58    59   if(bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))!=0) 60     return -1; 61   if(listen(sock ,1)!=0) 62     return -1; 63   return sock; 64 } 65  66 /********************************************************************** 67  * read_til_crnl(FILE* ) 68  * skip over all request info until a CRNL is seen 69  *********************************************************************/ 70 read_til_crnl(FILE* fp) { 71   char buf[BUFSIZ]; 72   while(fgets(buf, BUFSIZ, fp)!=NULL && strcmp(buf, "\r\n")!=0) 73     ; 74 } 75  76 /********************************************************************* 77  * process_rq(char* rq, int fd) 78  * do what the request asks for and write reply to fd 79  * handles request in a new process 80  * rq is HTTP command: GET /foo/bar.html HTTP/1.0 81  ********************************************************************/ 82 process_rq(char *rq, int fd) { 83   char cmd[BUFSIZ], arg[BUFSIZ]; 84   /*creat a new process and return if not the child*/ 85   if(fork()!=0)  86     return ; 87   strcpy(arg, "./");   /* precede args with .*/ 88   if(sscanf(rq, "%s %s", cmd, arg+2)!=2) 89     return ; 90   if(strcmp(cmd, "GET")!=0) 91     cannot_do(fd); 92   else if(not_exist(arg)) 93     do_404(arg, fd); 94   else if(isadir(arg)) 95     do_ls(arg, fd); 96   else if(ends_in_cgi(arg)) 97     do_exec(arg, fd); 98   else  99     do_cat(arg, fd);100 }101 102 103 104 /*********************************************************105  * the reply header thing: all functions need one106  * if content_type is NULL then don‘t send content type107  ********************************************************/108 header(FILE* fp, char * content_type) {109   fprintf(fp, "HTTP/1.0 200 OK\r\n");110   if(content_type)111     fprintf(fp, "Content-type: %s\r\n", content_type);112 }113 114 /********************************************************* 115  * simple functions first:116  *   cannot_do(fd): unimplemented HTTP command117  * and  do_404*(item ,fd)  no such object118  ********************************************************/119 120 cannot_do(fd) {121   FILE *fp=fdopen(fd, "w");122   123   fprintf(fp, "HTTP/1.0 501 Not Implemented\r\n");124   fprintf(fp, "Content-type: text/plain\r\n");125   fprintf(fp, "\r\n");126   127   fprintf(fp, "That command is not yet implemented\r\n");128   fclose(fp);129 }130 131 do_404(char* item, int fd) {132   FILE* fp=fdopen(fd, "w");133   134   fprintf(fp, "HTTP/1.0 404 Not Found\r\n");135   fprintf(fp, "Content-type:text/plain\r\n");136   fprintf(fp, "\r\n" );137   138   fprintf(fp, "The item you requested: %s\r\nis not found\r\n", item);139   fclose(fp);140 }141 142 /******************************************************************143  * the directory listing sectoin144  * isadir() uses stat, not_exist() uses stat145  * do_ls runs ls. It should not146  *****************************************************************/147 148 isadir(char *f) {149   struct stat info;150   return (stat(f, &info)!=-1 && S_ISDIR(info.st_mode));151 }152 153 not_exist(char *f) {154   struct stat info;155   return (stat(f, &info)==-1);156 }157 158 do_ls(char *dir, int fd) {159   FILE* fp;160   fp=fdopen(fd, "w");161   header(fp, "text/plain");162   fprintf(fp, "\r\n");163   fflush(fp);164   165   dup2(fd, 1);166   dup2(fd, 2);167   close(fd);168   execlp("ls", "ls", "-l",dir, NULL);169   perror(dir);170   exit(1);171 }172 173 /*******************************************************174  * the cgi stuff function to check extension and175  * one to run the program.176  ******************************************************/177 char * file_type(char* f) {178   /* returns ‘extension‘ of file */179   char *cp;180   if((cp=strrchr(f, .))!=NULL)181     return cp+1;182   return "";183 }184 185 ends_in_cgi(char* f) {186   return (strcmp(file_type(f) , "cgi")==0);187 }188 189 do_exec(char *prog, int fd) {190   FILE *fp;191   192   fp=fdopen(fd, "w");193   header(fp, NULL);194   fflush(fp);195   dup2(fd, 1);196   dup2(fd, 2);197   close(fd);198   execl(prog, prog, NULL);199   perror(prog);200 }201 202 /*******************************************************************203  * do_cat(filename, fd)204  * sends back contents after a header205  ******************************************************************/206 do_cat(char* f, int fd) {207   char *extension = file_type(f);208   char *content = "text/plain";209   FILE *fpsock, *fpfile;210   int c;211   212   if(strcmp(extension, "html")==0)213     content = "text/html";214   else if(strcmp(extension, "gif")==0)215     content = "image/gif";216   else if(strcmp(extension, "jpg")==0)217     content = "image/jpeg";218   else if(strcmp(extension, "jpeg")==0)219     content = "image/jpeg";220 221   fpsock = fdopen(fd, "w");222   fpfile = fopen(f, "r");223   if(fpsock != NULL && fpfile!=NULL) {224     header(fpsock, content);225     fprintf(fpsock, "\r\n");226     while((c=getc(fpfile))!=EOF)227       putc(c, fpsock);228     fclose(fpfile);229     fclose(fpsock);230   }231   exit(0);232 }

 

Linux_C socket 服务器(cat ,execl功能)