拿到一个项目首先先跑通,然后再慢慢来看代码,关于怎么将这个项目跑通,上一篇已经讲过,感兴趣的小伙伴可以移步下面的链接,或者其他博主的教程。
跑通后 ,我们先来看看这个服务器是怎么实现的。要知道怎么实现,首先就要知道服务器的工作流程是怎么样的 ,背后的原理是什么,这样更容易理解整个项目。
web服务器的工作流程
大致流程就是服务器会一直监听web端,如果有客户端发起请求,则创建线程处理用户的链接,与客户端(web端)建立连接,然后根据web端的需求来响应。那么具体的实现细节分解为几个部分来实现,可分为以下5个部分来实现(不是下面这个图,是下面的5个标题)
整个服务器的框架如下图所示:(来自于原作者)
上面的框架图就是该服务器项目的整体框架:总共就是3部分I/O处理、逻辑单元处理、存储处理。(一定要用面向对象的思想来理解为什么这么划分)。I/O处理就是服务器监听客户端,建立连接、读写网络数据(主线程负责监听),逻辑处理单元负责处理接收到的请求,执行业务逻辑,包括数据处理、计算、决策等操作(也就是工作线程负责处理连接请求,如:日志的输出、处理非活动链接、处理http请求(Http请求通常用的比较多的是get和post,不同的需求使用的请求不一样)。存储部分就是数据库存储客户端的信息数据等以及日志记录服务器的运行状态(例如链接了多少客户端等)。各个模块之间通过消息队列进行通信。知道大概结构后,再来一个一个细究。
1、web端和服务器端建立连接
参照项目原作者的号:两猿社(最新版Web服务器项目详解 - 00 项目概述)
这里涉及到I/O多路复用、边缘触发模式(ET)、proactor模式、线程池、get请求、post请求等知识点
采用epoll的边缘触发模式同时监听多个文件描述符,采用同步I/O模拟proactor模式处理事件,主线程负责监听客户端是否发起请求
当web端发起http请求时,主线程接收请求报文,然后将任务插入请求队列,由工作线程通过竞争从请求队列中获取任务
通过http类中的主从状态机对请求报文进行分析,根据请求报文对客户端进行http响应,然后由主线程给客户端发送响应报文。
5种I/O模型:
阻塞IO:调用者调用了某个函数,等待这个函数返回,期间什么也不做,不停的去检查这个函数有没有返回,必须等这个函数返回才能进行下一步动作
非阻塞IO:非阻塞等待,每隔一段时间就去检测IO事件是否就绪。没有就绪就可以做其他事。非阻塞I/O执行系统调用总是立即返回,不管时间是否已经发生,若时间没有发生,则返回-1,此时可以根据errno区分这两种情况,对于accept,recv和send,事件未发生时,errno通常被设置成eagain
信号驱动IO:linux用套接口进行信号驱动IO,安装一个信号处理函数,进程继续运行并不阻塞,当IO时间就绪,进程收到SIGIO信号。然后处理IO事件。
IO复用:linux用select/poll函数实现IO复用模型,这两个函数也会使进程阻塞,但是和阻塞IO所不同的是这两个函数可以同时阻塞多个IO操作。而且可以同时对多个读操作、写操作的IO函数进行检测。知道有数