在前面的文章中,我们已经实现了一个主从Reactor模型的服务器类,但是由于他只是一个服务器,不涉及任何业务以及协议的处理,那么为了方便用户使用,我们可以预先设置好协议的支持,只需要让用户进行业务处理就行了。
其实我们前面所说的新数据到来调用 Message 方法,他如果再细分的话,可以分成协议解析加业务处理,那么我们设计Http模块的目的就是完成协议解析的工作,那么未来使用者就只需要关心真正的业务处理的方法就行了,而对于协议解析工作则可以由库来提供。
那么未来我们的Http服务器需要提供哪些子模块呢?
首先,由于对于报文的解析大部分都是一些字符串的解析,所以我们可能会需要一些接口来以特定格式解析字符串。 同时由于是支持http协议,他可能会大量涉及到文件的读写,那么这些接口也是需要的,还有就是url中可能会有编码和解码的问题,这些功能其实都是我们后续会用到的,那么我们可以设置一个工具类来提供这些功能。
我们需要一个上下文模块,用来保存当前的连接的报文的解析进度,由于http是基于TCP的,后续收到的并不一定是一个完整的报文,所以我们需要对上下文进行保存。
那么http的上下文需要什么呢?其实最重要的就是保存解析的进度,也就是当前解析到了哪?下次解析从哪开始?是http报文的哪一部分?最终将一个报文解析完之后会返回一个HttpRuquest对象,也就是一个完整的请求。
当然还需要一个HttpRequest模块用来保存获取到的http请求的信息,他最主要的就是保存了获取到的请求的各项要素,比如版本号,请求路径,请求参数,请求方法,以及各种头部字段等,这些字段都是由Context在进行请求获取的时候进行填充的。 那么很显然,HttpRequest需要提供几个接口用于设置内部的各个字段。
还需要一个HttpResponse模块,用于保存响应的信息,响应的信息也很简单,无非就是状态码,状态码描述,版本,头部字段以及正文。他的方法也是一样的,提供一些接口用于设置这些字段,以及构建一个响应报文。
最后就是直接提供一个HttpServer模块,直接搭建一个用于处理解析Http协议的服务器,那么未来这个模块中会包含一个TcpServer模块,会包含四个回调方法(最重要的就是两个,一个是建立连接时需要设置上下文,一个是新数据到来时需要进行数据处理),然后还需要 hash_map 来保存请求与请求方法的映射表。
这里可能不理解的是最后一个要素,也就是请求和处理函数的映射表,为什么要这样设计呢?
因为未来我们的服务器是交给用户去使用的,用户可以根据请求的方法和请求的路径,来设置这样的请求该如何处理,比如我们提交的请求是 GET 方法,请求的路径是 /login ,那么我们的组件的使用者可能会将这个实际不存在的路径,作为登录请求的格式,那么未来用户会将登录请求的处理方法设置在hash map 中,我们的服务器其实不需要关心具体该如何处理,业务处理逻辑还是交给用户来设置的,而我们的服务器在处理的时候只需要在hash map 中去进行索引,找到对应的处理方法,将请求传递过去,在处理方法中构建一个响应,然后服务器再将这个响应返回给客户端就行了。这些hash map 的设计我们后续再来讲。
当然与此同时,我们就需要提供几个接口用于设置不同的请求方法的回调函数的哈希表,后续这些方法都是由用户自己提供的,包括服务器的根目录等都是用户自己进行设置,我们作为服务器的提供者是无法得知的。