2.Beast实现http的get请求

知识点

  1. 一个使用asio的服务器监听对端的消息需要一个上下文boost::asio::io_context,(上下文可以和底层iocp或epoll进行通信,底层有事件触发就会抛给上下文)。上下文是所有注册事件的基础,也就是事件的调度器,上下文会在底层不断地去轮询(如果想要监听socket读事件,把该事件放到底层的事件的注册表里,然后事件循环会不断地检测这个注册表,当发现socket有读事件就绪时,就会把消息抛给上层的上下文,上层的回调就会触发)。还需要一个端口unsigned short portio_context不存在拷贝构造
  2. boost::asio::ip::tcp::acceptor是接收器,主要用于接收对方的连接,要想使用accpetor需要与底层的事件循环去通信,那么就需要上下文作为媒介绑定上下文这个事件调度器去和底层的事件循环通信,那么底层才会把连接的事件抛给acceptor,进而才能触发回调函数
  3. boost::asio::ip::tcp::socket _socket,这个_socket是可以复用的,每有一个连接连过来的时候,总要有一个socket去接收对端一个连接的信息,那么socket就会对端之后传来的信息,然后把这些信息转给底层的一些连接的类后,之后这个socket还可以复用来接收新的连接。(socket没有拷贝构造,不支持复制)
  4. boost网络库中为什么要使用try catch ,因为当网络出现错误了,可能会当做异常来处理(比如对端不正常关闭)
  5. 定时器的调度需要通过底层的事件轮询来做,所以想要把定时器放到底层的事件循环,需要绑定一个能够调度的调度器:_socket.get_executor(socket自己的调度器),还需要绑定超时时间
  6. 为什么beast::error_code能够直接当做bool来使用:beast::error_code是一个类,重载了bool()用于隐式类型转换。
  7. 当建立socket连接后,将该连接抛给一个管理http连接的类HttpConnection,初始化是通过右值引用来初始化socket,之后开启HttpConnectionStart方法,通过boost的异步接收函数async_read来处理之后的请求,将请求读到一个8k大小的来自于beast网络库的缓冲区:beast::flat_buffer,将之打包成一个请求报文http::request<http::dynamic_body> _requst,这个请求报文是一个模板类,传入的类型是dynamic_body表示是一个动态的可接受的类型。
  8. HandleReq()的功能是给发送端返回一个Http报文,那么就需要对成员变量http::response<http::dynamic_body> _response进行设置,设置版本,设置是否keep_alive,对于请求报文的方法进行解析
  9. 服务端一般不要主动的关闭客户端,这样会造成TIME_WAIT的状态
  10. 如果智能指针被取出裸指针后delete怎么办?将析构设置为私有的,再定义一个辅助类,辅助类能够访问对象的析构函数
  11. 当两个类互相包含时,不要在头文件中互相包含(会出现互相引用的问题),常用的解决办法:在各自的.h文件中各自做一个对方的声明,在各自.cpp文件中引入对方的头文件(前置声明法)

流程总结

  1. 创建服务器对象CServer: std::make_shared<CServer>(ioc,port);之后再启动上下文的底层循环
  2. 启动服务器:self->Start();这一步意味着要建立异步接收
  3. 当正确接收到连接之后,将自身的socket转交给管理http连接的对象,让该对象处理来自对端的消息和数据
  4. 当http对象异步监听到来自对端的数据后,进行HandleReqCheckDeadline的处理
  5. HandleReq用于对消息进行响应,将具体的响应交给逻辑处理类LogicSystem来处理,调用它的回调函数

TODO:代码添加