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 one
106  * if content_type is NULL then don‘t send content type
107  ********************************************************/
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 command
117  * and  do_404*(item ,fd)  no such object
118  ********************************************************/
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 sectoin
144  * isadir() uses stat, not_exist() uses stat
145  * do_ls runs ls. It should not
146  *****************************************************************/
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 and
175  * 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 header
205  ******************************************************************/
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 }

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。