CSAPP Tiny web 服务器源码分析及搭建运行

本文详细分析了CSAPP中Tiny Web服务器的工作原理,涵盖了Web基础、HTTP协议、服务动态内容以及Tiny服务器的源码分析。讨论了HTTP请求和响应的结构,以及动态内容如何通过CGI传递参数。此外,还介绍了Tiny服务器的main函数、doit函数、read_requesthdrs函数、parse_uri函数、serve_static和serve_dynamic函数的实现,并提供了运行和调试的步骤。
摘要由CSDN通过智能技术生成

1. Web基础

web客户端和服务器之间的交互使用的是一个基于文本的应用级协议HTTP(超文本传输协议)。一个web客户端(即浏览器)打开一个到服务器的因特网连接,并且请求某些内容。服务器响应所请求的内容,然后关闭连接。浏览器读取这些内容,并把它显示在屏幕上。

对于web客户端和服务器而言,内容是与一个MIME类型相关的字节序列。常见的MIME类型:

MIME类型 描述
text/html HTML页面
text/plain 无格式文本
image/gif GIF格式编码的二进制图像
image/jpeg JPEG格式编码的二进制图像

web服务器以两种不同的方式向客服端提供内容:
1. 静态内容:取一个磁盘文件,并将它的内容返回给客户端
2. 动态内容:执行一个可执行文件,并将它的输出返回给客户端

统一资源定位符:URL

http://www.google.com:80/index.html

表示因特网主机 www.google.com 上一个称为 index.html 的HTML文件,它是由一个监听端口80的Web服务器所管理的。 HTTP默认端口号为80

可执行文件的URL可以在文件名后包括程序参数, “?”字符分隔文件名和参数,而且每个参数都用“&”字符分隔开,如:

http://www.ics.cs.cmu.edu:8000/cgi-bin/adder?123&456

表示一个 /cgi-bin/adder 的可执行文件,带两个参数字符串为 123 和 456

确定一个URL指向的是静态内容还是动态内容没有标准的规则,常见的方法就是把所有的可执行文件都放在 cgi-bin 目录中

2. HTTP

HTTP标准要求每个文本行都由一对回车和换行符来结束

(1)HTTP请求

一个HTTP请求:一个请求行(request line) 后面跟随0个或多个请求报头(request header), 再跟随一个空的文本行来终止报头

请求行: <method> <uri> <version>
HTTP支持许多方法,包括 GET,POST,PUT,DELETE,OPTIONS,HEAD,TRACE。
URI是相应URL的后缀,包括文件名和可选参数
version 字段表示该请求所遵循的HTTP版本

请求报头:<header name> : <header data> 为服务器提供了额外的信息,例如浏览器的版本类型
HTTP 1.1中 一个IP地址的服务器可以是 多宿主主机,例如 www.host1.com www.host2.com 可以存在于同一服务器上。
HTTP 1.1 中必须有 host 请求报头,如 host:www.google.com:80 如果没有这个host请求报头,每个主机名都只有唯一IP,IP地址很快将用尽。

(2)HTTP响应

一个HTTP响应:一个响应行(response line) 后面跟随0个或多个响应报头(response header),再跟随一个空的文本行来终止报头,最后跟随一个响应主体(response body)

响应行:<version> <status code> <status message>
status code 是一个三位的正整数

状态代码 状态消息 描述
200 成功 处理请求无误
301 永久移动 内容移动到位置头中指明的主机上
400 错误请求 服务器不能理解请求
403 禁止 服务器无权访问所请求的文件
404 未发现 服务器不能找到所请求的文件
501 未实现 服务器不支持请求的方法
505 HTTP版本不支持 服务器不支持请求的版本

两个最重要的响应报头:
Content-Type 告诉客户端响应主体中内容的MIME类型
Content-Length 指示响应主体的字节大小
响应主体中包含着被请求的内容。

3.服务动态内容

(1) 客户端如何将程序参数传递给服务器

GET请求的参数在URI中传递, “?”字符分隔了文件名和参数,每个参数都用一个”&”分隔开,参数中不允许有空格,必须用字符串“%20”来表示
HTTP POST请求的参数是在请求主体中而不是 URI中传递的

(2)服务器如何将参数传递给子进程

GET /cgi-bin/adder?123&456 HTTP/1.1

它调用 fork 来创建一个子进程,并调用 execve 在子进程的上下文中执行 /cgi-bin/adder 程序

在调用 execve 之前,子进程将CGI环境变量 QUERY_STRING 设置为”123&456”, adder 程序在运行时可以用unix getenv 函数来引用它

(3)服务器如何将其他信息传递给子进程
环境变量 描述
QUERY_STRING 程序参数
SERVER_PORT 父进程侦听的端口
REQUEST_METHOD GET 或 POST
REMOTE_HOST 客户端的域名
REMOTE_ADDR 客户端的点分十进制IP地址
CONTENT_TYPE 只对POST而言,请求体的MIME类型
CONTENT_LENGTH 只对POST而言,请求体的字节大小
(4) 子进程将它的输出发送到哪里

一个CGI程序将它的动态内容发送到标准输出,在子进程加载并运行CGI程序之前,它使用UNIX dup2 函数将它标准输出重定向到和客户端相关连的已连接描述符
因此,任何CGI程序写到标准输出的东西都会直接到达客户端

4. 综合: Tiny web 服务器源码及分析

(1) main程序

Tiny是一个迭代服务器,监听在命令行中传递来的端口上的连接请求,在通过调用 open_listenfd 函数打开一个监听套接字以后,执行无限服务器循环,不断接受连接请求(第16行),执行事务(第17行),并关闭连接它的那一端(第18行)

int main(int argc, char **argv)
{
        int listenfd, connfd, port, clientlen;
        struct sockaddr_in clientaddr;

        if (argc != 2) {
                fprintf(stderr, "usage
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值