一、Acceptor模块:这是一个对于通信连接进行整体管理的一个模块,对一个连接的操作都是通过这个模块来进行!
二、提供的功能
Acceptor模块是对Socket模块,Channel模块的⼀个整体封装,实现了对⼀个监听套接字的整体的管
理。
三、实现思想
(一)功能
- 实现向Channel提供可读事件的IO事件处理回调函数,函数的功能其实也就是获取新连接。
- 为新连接构建⼀个Connection对象出来。
(二)意义
当获取了一个新建连接的描述符后,需要为这个通信连接,封装一个connection对象,设置不同回调。
注意:因为Acceptor模块本身并不知道一个链接产生了某个事件该如何处理,因此获取一个通信连接后,Connection的封装,以及事件回调的设置都应该由服务器模块来进行!
(三)功能设计
回调函数设置——新建连接获取成功的回调设置,由服务器来指定!
四、框架
/*
Acceptor 模块,对监听套接字进行管理!
1. 创建一个监听套接字
2. 启动读事件监控
3. 事件触发后,获取新连接
4. 调用新连接获取成功后的回调函数!
4. 为新连接创建Connection进行管理(这一步不是Acceptor模块操作,应该是服务器模块)
因为Acceptor模块只进行监听连接的管理,因此获取到新连接的描述符后,对于新连接描述符如何处理并不关心!
对于新连接如何处理,应该是服务器模块关心管理!
服务器模块,实现了一个对于新连接描述符处理的函数,将这个函数设置给Acceptor模块的回调函数!
*/
五、代码
class Acceptor {
private:
Socket _socket; // 用于创建监听套接字
EventLoop *_loop; // ⽤于对监听套接字进⾏事件监控
Channel _channel; // ⽤于对监听套接字进⾏事件管理
using AcceptCallback = std::function<void(int)>;
AcceptCallback _accept_callback;
private:
/*监听套接字的读事件回调处理函数---获取新连接,调⽤_accept_callback函数进⾏新连接处理*/
void HandleRead() {
int newfd = _socket.Accept();
if (newfd < 0) {
return ;
}
if (_accept_callback) _accept_callback(newfd);
}
int CreateServer(int port) {
bool ret = _socket.createServer(port);
assert(ret == true);
return _socket.Fd();
}
public:
/*不能将启动读事件监控,放到构造函数中,必须在设置回调函数后,再去启动*/
/*否则有可能造成启动监控后,⽴即有事件,处理的时候,回调函数还没设置:新连接得不到处理,且资源泄漏*/
Acceptor(EventLoop* loop,int port) : _socket(createServer(port)),_loop(loop),_channel(loop,_socket.Fd()) {
_channel(loop, _socket.Fd()) {
_channel.SetReadCallback(std::bind(&Acceptor::HandleRead, this));
}
void SetAcceptCallback(const AcceptCallback &cb) {
_accept_callback = cb;
}
void Listen() {
_channel.EnableRead();
}
};