📄 tiny.c
字号:
/* $begin tinymain *//* * tiny.c - A simple, iterative HTTP/1.0 Web server that uses the * GET method to serve static and dynamic content. * SCO OpenServer5.0.6 Compiled By MoYuQuan BIT-BUPT */#include "csapp.h"void doit(int fd);void read_requesthdrs(rio_t *rp);int parse_uri(char *uri, char *filename, char *cgiargs);void serve_static(int fd, char *filename, int filesize);void get_filetype(char *filename, char *filetype);void serve_dynamic(int fd, char *filename, char *cgiargs);void clienterror(int fd, char *cause, char *errnum, char *shortmsg, char *longmsg);int main(int argc, char **argv) { int listenfd, connfd, port, clientlen; struct sockaddr_in clientaddr; /* Check command line args */ if (argc != 2) { fprintf(stderr, "usage: %s <port>\n", argv[0]); exit(1); } port = atoi(argv[1]); listenfd = Open_listenfd(port); while (1) { clientlen = sizeof(clientaddr); connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); doit(connfd); Close(connfd); }}/* $end tinymain *//* * doit - handle one HTTP request/response transaction *//* $begin doit */void doit(int fd) { int is_static; struct stat sbuf; char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], cgiargs[MAXLINE]; rio_t rio; /* Read request line and headers */ Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); /* telnet localhost 9000 GET / HTTP/1.1 default by browser sended is :GET|/index.html|HTTP/1.1 */ sscanf(buf, "%s %s %s", method, uri, version);#ifdef SCO_DEBUG printf("---------------SCO OpenServer5.0.6------------------------\n"); printf("%s|%s|%s\n", method, uri, version); printf("---------------SCO OpenServer5.0.6------------------------\n");#endif /* strcasecmp in /usr/include/strings.h */ if (strcasecmp(method, "GET")) { clienterror(fd, method, "501", "Not Implemented", "Tiny does not implement this method"); return; } read_requesthdrs(&rio); /* Parse URI from GET request */ is_static = parse_uri(uri, filename, cgiargs); printf("filename=(%s)|cgiargs=(%s)\n", filename,cgiargs); if (stat(filename, &sbuf) < 0) { clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file"); return; } if (is_static) { /* Serve static content */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't read the file"); return; } serve_static(fd, filename, sbuf.st_size); } else { /* Serve dynamic content */ if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) { clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program"); return; } serve_dynamic(fd, filename, cgiargs); }}/* $end doit *//* * read_requesthdrs - read and parse HTTP request headers *//* $begin read_requesthdrs */void read_requesthdrs(rio_t *rp) { char buf[MAXLINE]; Rio_readlineb(rp, buf, MAXLINE); /* input:[host : 192.9.200.100] */ printf("begin .............................\n"); printf("%s", buf); printf("end ...............................\n"); /* input the home.html ,input the enter \r and input the enter again \n (new line) that is "\r\n" */ //while(strcmp(buf, "\r\n")) {// while(memcmp(buf, "quit",4)) { while(strcmp(buf, "\r\n")) { Rio_readlineb(rp, buf, MAXLINE); printf("begin ---------------------------------------------------\n"); printf("%s", buf); printf("end ---------------------------------------------------\n"); } return;}/* $end read_requesthdrs *//* * parse_uri - parse URI into filename and CGI args * return 0 if dynamic content, 1 if static *//* $begin parse_uri */int parse_uri(char *uri, char *filename, char *cgiargs) { char *ptr; if (!strstr(uri, "cgi-bin")) { /* Static content */ strcpy(cgiargs, ""); strcpy(filename, "."); strcat(filename, uri); if (uri[strlen(uri)-1] == '/') strcat(filename, "index.html"); return 1; } else { /* Dynamic content */ ptr = index(uri, '?'); if (ptr) { strcpy(cgiargs, ptr+1); *ptr = '\0'; } else strcpy(cgiargs, ""); strcpy(filename, "."); strcat(filename, uri); return 0; }}/* $end parse_uri *//* * serve_static - copy a file back to the client *//* $begin serve_static */void serve_static(int fd, char *filename, int filesize) { int srcfd; char *srcp, filetype[MAXLINE], buf[MAXBUF]; /* Send response headers to client */ get_filetype(filename, filetype); sprintf(buf, "HTTP/1.0 200 OK\r\n"); sprintf(buf, "%sServer: Tiny Web Server\r\n", buf); sprintf(buf, "%sContent-length: %d\r\n", buf, filesize); sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype); Rio_writen(fd, buf, strlen(buf)); /* Send response body to client */ srcfd = Open(filename, O_RDONLY, 0); srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0); Close(srcfd);printf("return html beginning is ...........\n");printf("%s\n",srcp);printf("return html ending is ...........\n"); Rio_writen(fd, srcp, filesize); Munmap(srcp, filesize);}/* * get_filetype - derive file type from file name */void get_filetype(char *filename, char *filetype) { if (strstr(filename, ".html")) strcpy(filetype, "text/html"); else if (strstr(filename, ".gif")) strcpy(filetype, "image/gif"); else if (strstr(filename, ".jpg")) strcpy(filetype, "image/jpeg"); else strcpy(filetype, "text/plain");} /* $end serve_static *//* * serve_dynamic - run a CGI program on behalf of the client *//* $begin serve_dynamic */void serve_dynamic(int fd, char *filename, char *cgiargs) { char buf[MAXLINE], *emptylist[] = { NULL }; char envStr[200]; /* Return first part of HTTP response */ sprintf(buf, "HTTP/1.0 200 OK\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Server: Tiny Web Server\r\n"); Rio_writen(fd, buf, strlen(buf)); memset(envStr,0x00,sizeof(envStr)); if (Fork() == 0) { /* child */ /* Real server would set all CGI vars here setenv("QUERY_STRING", cgiargs, 1); */ sprintf(envStr,"QUERY_STRING=%s",cgiargs); putenv(envStr); Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */ Execve(filename, emptylist, environ); /* Run CGI program */ } Wait(NULL); /* Parent waits for and reaps child */}/* $end serve_dynamic *//* * clienterror - returns an error message to the client *//* $begin clienterror */void clienterror(int fd, char *cause, char *errnum, char *shortmsg, char *longmsg) { char buf[MAXLINE], body[MAXBUF]; /* Build the HTTP response body */ sprintf(body, "<html><title>Tiny Error</title>"); sprintf(body, "%s<body bgcolor=""ffffff"">\r\n", body); sprintf(body, "%s%s: %s\r\n", body, errnum, shortmsg); sprintf(body, "%s<p>%s: %s\r\n", body, longmsg, cause); sprintf(body, "%s<hr><em>The Tiny Web server</em>\r\n", body); /* Print the HTTP response */ sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Content-type: text/html\r\n"); Rio_writen(fd, buf, strlen(buf)); sprintf(buf, "Content-length: %d\r\n\r\n", strlen(body)); Rio_writen(fd, buf, strlen(buf)); Rio_writen(fd, body, strlen(body));}/* $end clienterror */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -