Acceptor类
Muduo中的acceptor类是对accept的一层简单封装,对外只提供listen接口和setNewConnectionCallnack接口
Acceptor类功能
实现对连接的accept并且调用持有该acceptor的类的newconnection来创建持有者想要连接
接口
///把fd和地址信息传递出去
typedef std::function<void (int, const InetAddress&)> NewConnectionCallback;
void setNewConnectionCallBack(const NewConnectionCallback& cb);
void listen();
bool isListening() const{
return m_isListen;
}
数据成员
void handleRead();
EventLoop *m_loop;///所属loop
Socket m_listenSocket;///监听的fd
Channel m_readChannel;///管理的channel
NewConnectionCallback m_acceptCb;
bool m_isListen;
int m_idleFd;
具体实现
CzyNetFrame::Acceptor::Acceptor(EventLoop *loop, const InetAddress &listenAddr, bool reusePort)
: m_loop(loop), m_listenSocket(sockets::createNonblockingOrDie(listenAddr.family())),
m_readChannel(m_loop, m_listenSocket.fd()), m_idleFd(::open("/dev/null", O_RDONLY | O_CLOEXEC))
{
assert(m_idleFd >= 0);
m_listenSocket.setReusePort(reusePort);
m_listenSocket.setReuseAddr(true);
m_listenSocket.bindAddress(listenAddr);
m_readChannel.setReadCb(std::bind(&Acceptor::handleRead, this));
}
构造函数只干三件事:1.设置好监听的socket,2.将处理读的channel绑定到属主loop上,3.设置好readChannel的读回调
void CzyNetFrame::Acceptor::listen()
{
m_loop->assertInLoopThread();
m_isListen = true;
m_listenSocket.listen();
m_readChannel.enableRead();
}
listen函数是暴露给外的接口,启动listen,并且通过channel对对方发起的连接的读事件改为感兴趣的状态
void CzyNetFrame::Acceptor::handleRead()
{
m_loop->assertInLoopThread();
InetAddress peerAddr;
int connfd = m_listenSocket.accept(&peerAddr);
if (connfd >= 0)
{
if (m_acceptCb)
{
m_acceptCb(connfd, peerAddr);
}
else
{
sockets::close(connfd);
}
}
else
{
LOG_SYSERR << " in acceptor ::handleRead too many connfd";
this tricks to defend two many client
if (errno == EMFILE)
{
::close(m_idleFd);
m_idleFd = ::accept(m_listenSocket.fd(), NULL, NULL);
::close(m_idleFd);
m_idleFd = ::open("/dev/null", O_RDONLY | O_CLOEXEC);
}
}
}
handleRead则实实在在的调用了linux系统下的accept,并且掉用通过设置的newConnection设置的回调