32muduo_net库源码分析(八)

来源:互联网 发布:网络推广维护 编辑:程序博客网 时间:2024/06/06 07:28

1.Acceptor

(1)Acceptor用于accept(2)接受TCP连接

(2)Acceptor的数据成员包括Socket、Channel,Acceptor的socket是listening socket(即serversocket)。Channel用于观察此socket的readable事件,并回调Accptor::handleRead(),后者调用accept(2)来接受新连接,并回调用户callback。

2.代码

1.Acceptor.h

// Copyright 2010, Shuo Chen.  All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is an internal header file, you should not include this.#ifndef MUDUO_NET_ACCEPTOR_H#define MUDUO_NET_ACCEPTOR_H#include <boost/function.hpp>#include <boost/noncopyable.hpp>#include <muduo/net/Channel.h>#include <muduo/net/Socket.h>namespace muduo{namespace net{class EventLoop;class InetAddress;////// Acceptor of incoming TCP connections.///class Acceptor : boost::noncopyable{ public:  typedef boost::function<void (int sockfd,                                const InetAddress&)> NewConnectionCallback;  Acceptor(EventLoop* loop, const InetAddress& listenAddr);  ~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_;};}}#endif  // MUDUO_NET_ACCEPTOR_H

2.Acceptor.cc

// Copyright 2010, Shuo Chen.  All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)#include <muduo/net/Acceptor.h>#include <muduo/net/EventLoop.h>#include <muduo/net/InetAddress.h>#include <muduo/net/SocketsOps.h>#include <boost/bind.hpp>#include <errno.h>#include <fcntl.h>//#include <sys/types.h>//#include <sys/stat.h>using namespace muduo;using namespace muduo::net;Acceptor::Acceptor(EventLoop* loop, const InetAddress& listenAddr)  : loop_(loop),    acceptSocket_(sockets::createNonblockingOrDie()),    acceptChannel_(loop, acceptSocket_.fd()),    listenning_(false),    idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC)){  assert(idleFd_ >= 0);  acceptSocket_.setReuseAddr(true);  acceptSocket_.bindAddress(listenAddr);  acceptChannel_.setReadCallback(      boost::bind(&Acceptor::handleRead, this));}Acceptor::~Acceptor(){  acceptChannel_.disableAll();  acceptChannel_.remove();  ::close(idleFd_);}void Acceptor::listen(){  loop_->assertInLoopThread();  listenning_ = true;  acceptSocket_.listen();  acceptChannel_.enableReading();}void Acceptor::handleRead(){  loop_->assertInLoopThread();  InetAddress peerAddr(0);  //FIXME loop until no more  int connfd = acceptSocket_.accept(&peerAddr);  if (connfd >= 0)  {    // string hostport = peerAddr.toIpPort();    // LOG_TRACE << "Accepts of " << hostport;    if (newConnectionCallback_)    {      newConnectionCallback_(connfd, peerAddr);    }    else    {      sockets::close(connfd);    }  }  else  {    // Read the section named "The special problem of    // accept()ing when you can't" in libev's doc.    // By Marc Lehmann, author of livev.    if (errno == EMFILE)    {      ::close(idleFd_);      idleFd_ = ::accept(acceptSocket_.fd(), NULL, NULL);      ::close(idleFd_);      idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC);    }  }}

3.Accepotr示例

void newConnection(int sockfd, const InetAddress& peerAddr){  printf("newConnection(): accepted a new connection from %s\n",         peerAddr.toIpPort().c_str());  ::write(sockfd, "How are you?\n", 13);  sockets::close(sockfd);}int main(){  printf("main(): pid = %d\n", getpid());  InetAddress listenAddr(8888);  EventLoop loop;  Acceptor acceptor(&loop, listenAddr);  acceptor.setNewConnectionCallback(newConnection);  acceptor.listen();  loop.loop();}


原创粉丝点击