概述
-This file is unterstanding the work method of Web Server
-The example is TinyHttp and I give some notes
Overview
main()
–>startup()
–>accept_request()
–>execute_cgi()
- Main senario:
- Establish a web server step
- 建立连接– accept connection from client
- Accept request – 读取一条HTTP报文
- Handle request – 解释报文,采取行动
- 访问资源 – 访问报文中指定的资源
- 构建报文 – 创建带有正确HTTP首部的报文
- 发送响应 – give the response to client
- 记录事务处理过程 – record the step into log <– No such info in TinyHttp
Create connection
- 如果client已经打开了持久链接,那么可以复用,否则客户端可以打开一条新连接。
- Web服务器会将新连接添加到现存的Web服务器列表中,做好监视链接上传数据的准备。
- Web server可以随意拒绝or立即关闭任意一条链接<==?? How, Need to check Nginx/APV/..??
- 客户端主机名识别–会降低性能。So many server close this function or permit it in some special cases.
Accept request message
- 解析请求行,查找请求方法、指定的资源标识符以及版本号,各项之间以一个空格分隔,并且以一个CRLF r作为行的结束
- 读取以 CRLF 结尾的报文首部
- 检测到以CRLF结尾的、标识首部结束的空行(如果有的话)
- 长度由content-length决定
- eg:
- TinyHttp采用多线程模型,没有使用复用IO模型,收到一个请求时,即listenning port get accept request,generate a thread to run accept_request function
int main(void):
/*建立socket,监听端口*/
++server_sock = startup(&port);
++while (1):
|__client_sock = accept(server_sock,
(struct sockaddr *)&client_name,
&client_name_len);/*recieve request message*/
|__if (pthread_create(&newthread , NULL, accept_request, (void*)client_sock) != 0):
perror("pthread_create");/* accept_request(client_sock),child thread to handle request*/
//close
++close(server_sock);
++return(0);
注意:pthread_create 第二个参数回调函数也要求是void* func(void*)三个参数是(void*) ,后面
void* accept_request(void* thread_arg) client_sock 作为参数传进来,用的时候要:
int client = (int)client_sock
/*对参数的读取放在get_line()里很关键一点要理解get_line的意思。
* 我们要知道当在浏览器中输入url后enter之后,它发给服务器是文本型的字符串,
* 遵循http请求格式,类似下面的:
* GET / HTTP/1.1
* HOST:www.abc.com
* Content-type:text/html
*...
* get_line干的事就是读取一行,并且不管原来是以n还是rn结束,均转化为以n再加 字符结束。其实现如下:*/
int get_line(int sock, char* buf, int size)
{
int i = 0;
int rcv_num = 0;
char c = '