Acceptor用于接收client的连接请求,建立连接
简介
类Acceptor主要功能socket、bind、listen,并调用注册的回调函数来处理新到的连接
连接建立
/处理时序图
1:当loop()函数监听到通道acceptChannel_有事件到来,即listen套接字可读时
2:acceptChannel_->handleEvent()
3:Acceptor::handleRead()
4:handleRead()函数中又调用了accept()接收客户端的请求
5:连接建立后,会调用注册的回调函数newConnectionCallback_()
Acceptor .h
头文件class Acceptor : noncopyable
{
public:
typedef std::function<void (int sockfd, const InetAddress&)> NewConnectionCallback;
Acceptor(EventLoop* loop, const InetAddress& listenAddr, bool reuseport);
~Acceptor();
void setNewConnectionCallback(const NewConnectionCallback& cb)
{ newConnectionCallback_ = cb; }
bool listenning() const { return listenning_; }
void listen();
private:
void handleRead();
EventLoop* loop_;
Socket acceptSocket_; //监听套接字
Channel acceptChannel_;//通道
NewConnectionCallback newConnectionCallback_;
bool listenning_;
int idleFd_;
};
构造函数
Acceptor创建非阻塞的listen socket和channel,并且将Acceptor::handleRead函数设置为acceptChannel_的Read Callback
Acceptor::Acceptor(EventLoop* loop, const InetAddress& listenAddr, bool reuseport)
: loop_(loop), //所属的loop
acceptSocket_(sockets::createNonblockingOrDie(listenAddr.family())), //创建非阻塞的listen套接字
acceptChannel_(loop, acceptSocket_.fd()), //创建监听Channel
listenning_(false), //是否正在监听
idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC)) //预留idlefd
{
assert(idleFd_ >= 0);
acceptSocket_.setReuseAddr(true); //设置地址、端口复用
acceptSocket_.setReusePort(reuseport);
acceptSocket_.bindAddress(listenAddr); //bind
//设置ReadCallback,下面在Acceptor::listen()中acceptChannel_.enableReading();
//==>当acceptChannel_有读事件(接收到新连接)时,将调用回调函数Acceptor::handleRead()
acceptChannel_.setReadCallback(
std::bind(&handleRead, this));
}
void Acceptor::handleRead()
{
loop_->assertInLoopThread();
InetAddress peerAddr;
int connfd = acceptSocket_.accept(&peerAddr);//accept新连接
if (connfd >= 0) //如果accept返回成功
{
if (newConnectionCallback_) //调用newConnectionCallback_回调函数
{
newConnectionCallback_(connfd, peerAddr);
}
else
{
sockets::close(connfd);
}
}
else
{
LOG_SYSERR << "in Acceptor::handleRead";
if (errno == EMFILE) //解决太多的文件描述符的错误:使用idlefd
{
::close(idleFd_);
idleFd_ = ::accept(acceptSocket_.fd(), NULL, NULL);
::close(idleFd_);
idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC);
}
}
}
Acceptor::listen()
,这个函数顾名思义,就是开始监听对端的连接请求void Acceptor::listen()
{
loop_->assertInLoopThread();
listenning_ = true;
acceptSocket_.listen();
acceptChannel_.enableReading(); //关心读事件
}
setNewConnectionCallback
accept返回后,即连接建立成功后,会执行注册的newConnectionCallback_函数
//设置[连接建立成功的回调函数]
void setNewConnectionCallback(const NewConnectionCallback& cb)
{ newConnectionCallback_ = cb; }
#include "Acceptor.h"
#include "EventLoop.h"
#include "InetAddress.h"
#include "SocketsOps.h"
#include
void newConnection(int sockfd, const muduo::InetAddress& peerAddr)
{
printf("newConnection(): accepted a new connection from %s\n",
peerAddr.toHostPort().c_str());
::write(sockfd, "How are you?\n", 13);
muduo::sockets::close(sockfd);
}
int main()
{
printf("main(): pid = %d\n", getpid());
muduo::InetAddress listenAddr(9981);
muduo::EventLoop loop;
muduo::Acceptor acceptor(&loop, listenAddr);
acceptor.setNewConnectionCallback(newConnection);
acceptor.listen();
loop.loop();
}