文章目录
这里是实现的代码
https://download.csdn.net/download/qq_43390943/11184422
文件
编译
运行
总结
/*
* 主要的设计思路:
* 1、首先要熟悉reactor的整个设计的模式,主线程负责链接新的客户端,在线程池中获取一个EventLoop来监听这个新产生的文件描述符
* 2、一个线程可以监听多个文件描述符,当有读写事件发生的时候,EventLoop将通知对应的事件分发器(这里每一个文件描述符对应一个事件分发器)
* 3、事件分发器开始分发事件,(这里在是调用相应的回调函数)
* 4、因为这里是一个线程监听多个文件描述符,如果读事件上的recv迟迟接收不到数据,不能因为recv阻塞而影响其他的线程事件的执行,所以这里的
* 事件都要设置成非阻塞的。
* 5、因为是非阻塞模式,可能因为系统的发送与接收缓冲区已满而导致send 和 recv 返回-1的情况,所以这里要在应用层上设计一个缓冲区,来保存
* 未发送完的数据,并在文件描述符上注册写事件,当可以写的时候,再次进行发送。
*
* 程序运行的主要流程:
* 1、启动程序,启动线程池,等待链接
* 2、当有新的链接到达的时候,主线程负责建立一个链接,然后获取一个事件循环器EventLoop来监听新的文件描述符。
*
* 具体实现上出现的问题:
* 1、怎样实现一个线程一个EventLoop各个线程之间可以互相通信互不影响 ?
* 在开启线程池的时候,创建与线程池形同个数的EventLoop 对象,让每个线程去执行不同的EventLoop对象中的监听函数,
* 在EventLoop 对象中设置一个threadId变量,存放执行该对象监听函数的线程的Id。这样就将线程与EventLoop对象一一对应了
* 可以根据这个来判断执行该EventLoop对象中的函数的线程是不是合法线程。
*
* 2、当主线程接受到请求的时候,其余线程都在监听状态,怎样将新产生的文件描述符加入到监听状态的线程的监听队列中
* 主线程首先获取一个EventLoop对象,然后执行该EventLoop对象的添加文件描述符的函数,但是执行该函数的现在是主线程,主线程
* 不能直接在子线程的监听队列中添加文件描述符,这时候主线程就将该任务添加到子线程的任务队列,然后唤醒子线程去执行
* 这样就可以添加一个文件描述符了。
*
* 3、怎样规避线程之间的交互访问,比如:不能通过1号线程调用2号线程的添加文件描述符与删除文件描述符的函数
* 每个EventLoop 对象都有一个执行该线程的合法的threadId ,如果1号线程想要执行2号线程中的函数的时候,函数中会先判断当前线程是不是2号线程
* 如果是,执行函数,如果不是,唤醒2号线程,由2号线程来执行。
*
* 4、怎样能够使得函数在各个类之间可以灵活的调用
*
* (回掉函数 )
* 5、怎样同一处理回调函数的参数不同的问题
* (对于同一个事件,不同的客户端的处理方式可能不同,传入的参数也可能不同){bind + function} 设置固定长度参数的
* 回调函数
*
* 6、EventLoopThreadPool 线程池的实现上思路?
* 创建指定个数的线程,创建一个任务队列,如果任务队列为空,线程进入睡眠状态,
* 如果队列不为空,线程从队列中取出一个任务开始执行,如果队列为满,添加任务的线程进入睡眠状态,直到队列中有任务被处理
* 唤醒线程添加任务。
*
* 7、Poller实现为纯虚函数,可以选择采用poll 或 epoll的方式来监听文件描述符
*
* 8、buffer 的设计思路:首先buffer的大小设置默认情况下为4k的大小,这里分为两种情况的考虑
* (1)sendBuff 当系统的send 缓冲区的内容满了的时候,我们send无法将所有的数据都写入系统的send缓冲区,同一个线程有多个文件描述符在等待,
* 所以这里不能阻塞直到可以写为止,只是非常浪费cpu资源的,所以设置一个应用层的缓冲区,将未发送的数据放入缓冲区中,并开始监听该文件
* 描述符上的写事件。当有事件到达的时候,之间将缓冲的去的内容写入,这次也不一定将缓冲区的内容全部发送,如果不能全部发送,继续监听写
* 事件,如果可以全部发送,则取消事件的发送。
* (2) 对于recv 缓冲区的考虑,是在用户端控制,还是在TcpConnection.cpp中控制现在还无法确定。
*
* 这里就是我对于muduo网络库的了解之后,自己单独拿出reactor模式来实现的代码,如果哪里不对,欢迎指出,^_^
*/