toyws 玩具式 web server
原文链接 http://woodrat.xyz/2015/07/18/toyws%e7%8e%a9%e5%85%b7%e5%bc%8f-web-server/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
csapp 上网络编程一章里有一个 tiny.c ,实现了 HTTP 的 GET 方法,支持 cgi 。照着书上自己敲了一个,取名 toyws 。后续准备把其他几个 HTTP METHOD 实现一下。
代码地址 toyws
根据 RFC-2616
HTTP messages 分为 request 和 response
HTTP-message = Request | Response ; HTTP/1.1 messages
server 接受client的连接后,client 发送一个 request message 到 server。server 处理后回复一个 response。
所以程序大致的流程就是
server start listen -> client connect -> server accept -> client send message -> server response message。
server 开始监听后进入一个死循环,不断处理客户端的连接和消息。
流程和普通的 socket 程序一样,只是需要按照 HTTP 协议 发送和回复消息。
request 和 response 消息使用 RFC-822 generic message format。
格式如下
generic-message = start-line *(message-header CRLF) CRLF [ message-body ]
两种类型的请求都包含一个 start-line,一行或多行 message-header,一个空行表示 heade r结束(每一行由 CRLF 即 \r\n 结束。),也许有一个 body。
一条 start-line 可能为 Request-Line 或者 Status-Line
start-line = Request-Line | Status-Line
若为 Request-Line,则格式如下
Request-Line = Method SP Request-URI SP HTTP-Version CRLF 例如
GET / HTTP/1.0
由于在我们的toyws暂时只实现 GET 方法,在 Request 中,只需要读取 request-line 中的 URI 一项,检查是否合法是否存在,然后返回 URI 指定的资源即可。
在服务器返回的 Response-Line 中,start-line 则为 Status-Line, Status-Line 的格式如下 :
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
Status-Code 代表的意义在 RFC-2616 中可以找到。在这里我们只用管 URI 是否合法,是否存在,存在则返回 200 OK ,不存在或者不能读取就返回 404 Not Found,若存在而无权限访问则返回 403 Forbidden。
Response 的完整定义如下 :
Response = Status-Line ; Section 6.1 *(( general-header ; Section 4.5 | response-header ; Section 6.2 | entity-header ) CRLF) ; Section 7.1 CRLF [ message-body ] ; Section 7.2
在返回的 Response 中,我们只实现 message-header 中的 entity-header 里 Content-Length 和 Content-Type 两项,告诉客户端返回的文件的大小和文件的类型。
最后,只用将内容加入到 message-body 中即可。
实现 POST 方法时,需要读取 Request Header 里面的 Content-Type 一项,默认为application/x-www-form-urlencoded
。
同时也需要读取 Content-Length,得到 Request Body 的长度。
根据 generic message format,连续两个 CRLF后即是 Request Body,按得到的 Content-Length 读取即可。