C++网络编程实战项目--Sinetlib网络库(4)——线程池和整体框架

xiaoxiao2025-06-08  17

线程池

我们已经有了一个Looper类表示事件循环,且每个线程只能有一个Looper,现在我们把Looper和线程绑定在一起,成为一个新的类LooperThread

创建该类也就创建了一条新线程,然后该线程上运行着Looper。我们把这些线程都交由线程池管理,也就是ThreadPool

Reactor

实际上这并不是纯粹的Reactor模式,更应该称之为半同步半异步模式。 我们有一个主线程以及线程池中的N个线程,主线程只负责监听socket,所有的connect请求都有主线程处理。当有新连接到来时,主线程接受并建立连接。

连接建立后,主线程会从线程池中选择一个线程,将连接分配给该线程,以后该连接上的所有请求都只有该线程处理。

抽象连接Connection

为了方便管理,我们把TCP连接抽象成一个类Connection

该类的私有数据成员如下,该类拥有连接两端的地址,以及各个状态下的回调函数,比如当连接上有消息到来时就会调用message_arrival_cb_。同时每个连接都会有输入输出缓冲区,用来接收消息和发送消息,具体的设计请看这里:Muduo 设计与实现之一:Buffer 类的设计

class Connection : public std::enable_shared_from_this<Connection> { private: Looper* loop_; // 连接描述符 const int conn_sockfd_; std::shared_ptr<EventBase> conn_eventbase_; // 服务器、客户端地址结构 struct sockaddr_in local_addr_; struct sockaddr_in peer_addr_; // 连接建立回调 Callback connection_established_cb_; // 消息到达 MessageCallback message_arrival_cb_; // 答复完成 Callback reply_complete_cb_; // 连接关闭 Callback connection_close_cb_; // 结束自己生命的回调 Callback suicide_cb_; // 输入输出缓冲区 IOBuffer input_buffer_; IOBuffer output_buffer_; };

Server类

这个就是整个网络库的最顶层的类了Server,用户使用该库也是直接使用该类。

简单讲一下,这个类无非就是上面图中的主线程,它创建并监听socket,有连接到来就接受并将其分配给工作线程。一点比较重要的就是Connection对象生命期的管理了。

实际上,我们抽象出来的连接Connection仍旧是由主线程管理的,只不过是把它的函数拿到工作线程上执行,包括消息到达时的处理函数、连接断开的处理函数等。

那么这里就会产生一个问题,当连接断开时,在Looper_1上如何让Connection对象销毁掉呢?如果直接在连接断开的处理函数里面销毁,不就相当于在自身的函数里销毁自身,显然这样的自杀方式不可取,也不够优雅。

我们的实现是把自杀变成他杀,在连接断开的处理函数里向主线程投放一个任务,请求他把这个Connnection对象销毁掉,这样销毁Connection的工作就由主线程Looper来干,而不是这个Connection自己。

小结

到这里网络库的部分就差不多了,虽然仍旧有很多问题没考虑到,但基本上也把整体的框架梳理了一下。关于代码,应该还是有很多可以改进的地方,希望读者能提下pull requests帮助改进。后续有时间再讲一下http服务器部分的代码。

转载请注明原文地址: https://www.6miu.com/read-5031508.html

最新回复(0)