当前位置:
文档之家› Socket实现Web服务器
Socket实现Web服务器
clientlen = sizeof(clientaddr); connfd = accept(listenfd, (SA *)&clientaddr, &clientlen); doit(connfd); close(connfd); }
2.3 模块 2
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, "403", "Forbidden", "Tiny couldn't run the CGI program");
return; } serve_dynamic(fd, filename, cgiargs); }
2.4 模块 3
void serve_static(int fd, char *filename, int filesize) {
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); }
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)) {
if (fork() == 0) /* child */ {
setenv("QUERY_STRING", cgiargs, 1); dup2(fd, STDOUT_FILENO); execve(filename, emptylist, environ); } wait(NULL); }
3 运行结果
1.2 HTTP 响应
一个 HTTP 响应的组成是这样的:一个响应行、0 个或多个响应报头、一个空行、响应主体。 响应行:<version> <status code> <status message> 200 OK 400 Bad Request 401 Unauthorized 403 Forbidden 404 Not Found 响应报头格式与请求报头格式一样。具体的可参考下面的实验。
Socket 实现 Web 服务器
1 HTTP 协议简介
这里主要讨论 HTTP GET。
1.1 HTTP 请求
一个 HTTP 请求的组成是这样的:一个请求行、0 个或多个请求报头、一个空行。 请求行:<method><uri><version> method 有:GET POST HEAD PUT DELETE TRACE CONNECT OPTIONS 请求报头:由多个<header name>: <header data>组成
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)) {
3.1 获取静态网页
3.2 获取动态网页
4 参考资料
(1) /rfc/rfc2616.txt HTTP 1.1 协议 (2) 《深入理解计算机系统》
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);
2.5 模块 4
void serve_dynamic(int fd, char *filename, char *cgiargs) {
char buf[MAXLINE], *emptylist[] = { NULL };
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));
1.3 telnet 实验 HTTP GET
2 Web 服务器的简单实现
主要采用 socket 编程同时遵循 HTTP 协议,实现静态页面和动态页面的获取。参考《深入 理解计算机系统》 Tiny Web 服务器的实现。
2.1 程序流_listenfd(port); while (1) {