简易Web服务器

来源:互联网 发布:点击访问fc2最新域名 编辑:程序博客网 时间:2024/05/22 15:59

老早就学习了Web服务器, 那是在《深入理解计算机系统》后面有个例子是有关Web服务器的,并给了一个简单的例子。

例子包含3个文件,csapp.h, csapp.c, tiny.c。现将tiny.c列出来。

/* * tiny.c - A simple, iterative HTTP/1.0 Web server that uses the *          GET method to serve static and dynamic content */#include "csapp.h"void doit(int fd);void read_requesthdrs(rio_t *rp);int parse_uri(char *uri, char *filename, char *cgiargs);void server_static(int fd, char *filename, int filesize);void get_filetype(char *filename, char *filetype);void server_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);}}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);sscanf(buf, "%s %s %s", method, uri, version);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);if (stat(filename, &sbuf) < 0){clienterror(fd, filename, "404", "Not found", "Tiny couldn't find this file");return;}    if (is_static){if( !(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)){clienterror(fd, filename, "403", "FOrbidden", "tiny couldn't read the file");return ;}server_static(fd, filename, sbuf.st_size);}else{if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)){clienterror(fd, filename, "403", "Forbidden", "Tiny couldn't run the CGI program");return ;}server_dynamic(fd, filename, cgiargs);}}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\bn", 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-lengt:%d\r\n\r\n", (int)strlen(body));Rio_writen(fd, buf, strlen(buf));Rio_writen(fd, body, strlen(body));}void read_requesthdrs(rio_t *rp){char buf[MAXLINE];Rio_readlineb(rp, buf, MAXLINE);while (strcmp(buf, "\r\n")){Rio_readlineb(rp, buf, MAXLINE);printf("%s", buf);}return;}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, "home.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;}}void server_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);Rio_writen(fd, srcp, filesize);Munmap(srcp, filesize);}/* * GET -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");}}void server_dynamic(int fd, char *filename, char *cgiargs){char buf[MAXLINE], *emptylist[] = { };/* 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));if (Fork() == 0) /* child */{/* Real server would set all CGI vars here */setenv("QUERY_STRING", cgiargs, 1);Dup2(fd, STDOUT_FILENO);Execve(filename, emptylist, environ);} Wait(NULL);}

现在我知道了Web服务器到底是什么概念了,它和普通的服务器有什么区别了。。。

Web服务器比如http服务器它就是实现了http协议的服务器,当然我们也可以自定义自己的协议。

但是底层都是使用tcp/ip协议来传输数据的。



0 0
原创粉丝点击