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

线程池

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

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

Reactor

实际上这并不是纯粹的Reactor模式,更应该称之为半同步半异步模式。
我们有一个主线程以及线程池中的N个线程,主线程只负责监听socket,所有的connect请求都有主线程处理。当有新连接到来时,主线程接受并建立连接。
C++网络编程实战项目--Sinetlib网络库(4)——线程池和整体框架_第1张图片

连接建立后,主线程会从线程池中选择一个线程,将连接分配给该线程,以后该连接上的所有请求都只有该线程处理。
C++网络编程实战项目--Sinetlib网络库(4)——线程池和整体框架_第2张图片

抽象连接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仍旧是由主线程管理的,只不过是把它的函数拿到工作线程上执行,包括消息到达时的处理函数、连接断开的处理函数等。
C++网络编程实战项目--Sinetlib网络库(4)——线程池和整体框架_第3张图片

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

我们的实现是把自杀变成他杀,在连接断开的处理函数里向主线程投放一个任务,请求他把这个Connnection对象销毁掉,这样销毁Connection的工作就由主线程Looper来干,而不是这个Connection自己。
C++网络编程实战项目--Sinetlib网络库(4)——线程池和整体框架_第4张图片

小结

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

你可能感兴趣的:(网络)