一个Web Server的基本要素(基础篇)

什么是Web Server

Web Server 就是一个服务器软件,或者是运行这个服务器软件的硬件。通过HTTP协议与客户端通信,可以接收、存储、处理来自客户端的HTTP请求,并做出HTTP响应,返回客户端请求的资源。

用户如何与服务器通信

用户通常使用web浏览器来与Web Server进行通信,在浏览器键入域名或者ip加端口,李兰器就会解析域名成ip地址或者直接根据ip地址对服务器发送http请求,期间要进行tcp的三次握手建立连接。

服务器如何接收用户请求

服务器通过socket监听来自用户的请求。要经过创建socket、配置地址、绑定地址和端口(bind)、开启监听(listen)、接收连接(accept)等几个步骤。
接收连接之后,需要分配一个逻辑单元来处理连接请求,同时还需要继续监听其他请求。在这里可以使用io多路复用以线程池提高并发处理请求的效率。

服务器要处理的三类事件

IO事件、信号及定时事件。
有两种处理事件的模式:Reactor和Proactor。
Reactor模式要求主线程只负责监听文件描述符是否有事件发生(可读、可写),若有,就通知工作线程(逻辑单元),将socket可读可写事件放入请求对列,交给工作线程。
Proactor模式将所有的IO操作都交给主线程和内核处理,工作线程只负责处理逻辑。主线程完成读取完成后,选择一个工作线程来处理客户请求。

作为服务器开发者,需要掌握linux下的三种IO复用方式,select、poll、epoll,以及同步IO和异步IO的区别。

linux的三种系统调用

对于select和poll,所有文件描述符都是在用户态被加入文件描述符集合里的。每次调用都需要将整个集合拷贝到内核态。epoll则将整个文件描述符结合维护在内核态,每次添加文件描述符都只需要一个系统调用。

select使用线性表描述文件描述符集合,文件描述符有上限,poll使用链表来描述文件描述符集合。epoll底层通过红黑树来描述,并维护一个ready_list,将事件表中已就绪文件添加到ready_list中,使用epoll_wait仅观察ready_list中有无数据。

select和poll最大的开销来自内核判断文件描述符就绪这一过程,每次执行select和poll调用时,他们会遍历整个文件描述符集合去判断每个文件描述符是否就绪。epoll在有文件描述符就绪时会以自动触发回调函数,将就绪的文件描述符加入ready_list 中,等待epoll_wait获取。

select和poll都只能工作在相对低效的LT模式下,epoll同时支持LT和ET模式。

综上,当监听的文件描述符较少时,建议用select和poll,当监听的文件描述符较多且活跃的较少时,建议使用epoll

LT(电平触发),去遍历事件表中每个文件描述符,观察是否有文件描述符就绪,如有,epoll_wait会以非阻塞方式返回,如果当次没处理,则该事件还会被后续的epoll_wait触发
ET(边缘触发),发现有事件就绪,就立即返回,若当时没有处理,下次也不会触发。

同步IO和异步IO

同步(阻塞)IO,在一个线程中,CPU执行代码的速度很快,一旦遇到IO操作,如读写文件,发送数据时,就需要等待IO操作完成,才能继续下一步操作。
异步(非阻塞)IO,当代码需要执行一个耗时的IO操作,它只发出IO指令,并不等待IO结果就去执行其他代码了,一段时间后,当IO返回结果,再通知CPU处理。

Web服务器如何处理及响应HTTP请求

可以使用线程池并发处理用户请求,主线程负责读写,工作线程负责处理逻辑(解析http报文等)。在之前的操作中,我们将服务器监听文件描述符中到达的客户连接请求接收,返回用于和用户通信的文件描述符,将这个文件描述符注册到epoll的内核事件表中,等待用户发送http请求。当epoll_wait发现此文件描述符就绪,主线程就将这个文件描述符上的HTTP报文读取到对应的用户缓存中作为一个任务对象,然后将这个任务对象的指针插入到线程池的请求对列中。

如何处理HTTP报文

首先要读取用户文件描述符上的数据,也就是http请求报文,http请求报文主要由请求行、请求头部、空行和请求数据四个部分组成。有两种请求报GET和POST,GET把参数包含在URL中,POST则通过request body传递参数。GET请求在URL中传送参数是有长度限制的。

后记

千里之行,始于足下。你还没有成功,那就代表你做的还不够,差点火候,日积月累必不可少。

你可能感兴趣的:(服务器,c++)