Muduo Network Library Source Code Analysis (v) acceptor and TCPServer class

Source: Internet
Author: User

First, let's mention the encapsulation of the socket (not complicated, so simply say).


Endian.h: Encapsulates a byte-order conversion function (global function, in the Muduo::net::sockets namespace).

socketsops.h/socketsops.cc: Encapsulates a socket-related system call.

socket.h/socket.cc (Socket Class): Encapsulates the socket file descriptor with the Raii method.

inetaddress.h/inetaddress.cc (InetAddress Class): Internetwork address sockaddr_in encapsulation.


A few important functions:

void Socket::settcpnodelay (bool on)//disable Nagle algorithm {  int optval = on? 1:0;  :: setsockopt (Sockfd_, Ipproto_tcp, Tcp_n Odelay,               &optval, sizeof optval);  Fixme check}void socket::setreuseaddr (bool on)//time_wait lower port multiplexing {  int optval = on? 1:0;  :: SetSockOpt (Sockfd_, Sol_socket, SO_REUSEADDR,               &optval, sizeof optval);  Fixme check}void socket::setkeepalive (bool on)//periodically detects if the connection exists {  int optval = on? 1:0;  :: setsockopt (Sockfd_, Sol_ SOCKET, So_keepalive,               &optval, sizeof optval);  Fixme CHECK}
Note the point:

(1) Nagle algorithm can avoid network congestion to some extent; disabling the Nagle algorithm avoids delays in successive packets, which is important for writing low-latency network services. Tcp_nodelay option to disable Nagle algorithm.

(2) __attribute__ ((deprecated)) indicates that the function is obsolete, eliminated, using such a function will warn you when compiling!


Acceptor

The class acceptor is used to listen, accept, and call the callback function to handle the new connection. After accept, if a new connection arrives, the Handleread () function is called, and the connection is received in this function. Each time a new connection is received in the Handleread () function, the callback function (if any) that handles the new connection is called.

Acceptor.h

<span style= "Font-family:microsoft yahei;color: #362e2b;" >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)//Set callback user's function  {newconnectioncallback_ = cb;}  BOOL Listenning () const {return listenning_;}  void Listen (); Private:  void Handleread ();  eventloop* Loop_;  Socket acceptsocket_;  Channel Acceptchannel_;  Newconnectioncallback Newconnectioncallback_;  BOOL Listenning_;  int idlefd_;}; </span>


acceptor.cc

<span style= "Font-family:microsoft yahei;color: #362e2b;" >acceptor::acceptor (eventloop* loop, const inetaddress& LISTENADDR): Loop_ (Loop), acceptsocket_ (Sockets::crea Tenonblockingordie ()), 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 (&AMP;PEERADDR);//True Receive connection if (CONNFD >= 0) {//String    Hostport = Peeraddr.toipport (); LOG_trace << "accepts of" << Hostport; if (newconnectioncallback_) {newconnectioncallback_ (CONNFD, peeraddr);//New Message returns callback function} 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); }}}</span>


TCPServer


The customer does not directly use acceptor, which is encapsulated in the TCPServer. TCPServer is simple to use, directly set the new connection arrival and message arrival callback function, and then start.
The Eventloopthreadpool is also encapsulated in the TCPServer, so the EventLoop object in TCPServer is the main reactor,eventloopthreadpool for Sub Reactor.
When the new connection arrives, TCPServer creates a new Tcpconnection object to hold the connection, sets the callback function for the new connection, Then take a EventLoop object in Eventloopthreadpool as the reactor for this new connection. TCPServer saves the tcpconnection in the current server object with a map, and when the TCPServer object is refactored, all connections are closed.


TcpServer.h

<span style= "Font-family:microsoft yahei;color: #362e2b;"  >///TCP Server, supports single-threaded and Thread-pool models.//////This is a interface class, so don ' t expose too Much details.class tcpserver:boost::noncopyable{public://typedef boost::function<void (eventloop*) >  Threadinitcallback;  TCPServer (eventloop* loop, const inetaddress& LISTENADDR);  TCPServer (eventloop* loop, const inetaddress& LISTENADDR, const string& namearg);  ~tcpserver ();  Force Out-line Dtor, for SCOPED_PTR members.  Const string& Hostport () const {return hostport_;}  Const string& Name () const {return name_;}  Starts the server if it ' s not listenning.  It ' s harmless to call it multiple times.  Thread safe.  void Start ();  Set Connection callback.  Not thread safe.  Set connection arrival or connection close callback function void Setconnectioncallback (const connectioncallback& cb) {connectioncallback_ = cb;}  Set message callback. Not threAd safe.  Set message arrival callback function void Setmessagecallback (const messagecallback& cb) {messagecallback_ = cb;} private://Not thread  Safe, but in loop void newconnection (int sockfd, const inetaddress& PEERADDR);  typedef std::map<string, tcpconnectionptr> Connectionmap;  eventloop* Loop_; The acceptor Loop const string hostport_;//service Port const string name_;//service name boost::scoped_ptr<acceptor> accepto R_;  Avoid revealing acceptor connectioncallback connectioncallback_;  Messagecallback Messagecallback_;  BOOL Started_; Always in loop thread int nextconnid_;//next connection ID connectionmap connections_;//connection list};</span>


tcpserver.cc

<span style= "Font-family:microsoft yahei;color: #362e2b;"  >tcpserver::tcpserver (eventloop* loop, const inetaddress& LISTENADDR, const string& namearg): Loop_ (Check_notnull (Loop)), Hostport_ (Listenaddr.toipport ()), Name_ (Namearg), Acceptor_ ( New Acceptor (loop, listenaddr)),/*threadpool_ (New Eventloopthreadpool (Loop)), Connectioncallback_ (defaultconnectio Ncallback), Messagecallback_ (defaultmessagecallback), */Started_ (FALSE), nextconnid_ (1) {//Acceptor::handleread The function will be callback with tcpserver::newconnection//_1 corresponding to the socket file descriptor, _2 corresponding to the address of the peer (inetaddress) acceptor_-> Setnewconnectioncallback (Boost::bind (&tcpserver::newconnection, this, _1, _2));}  Tcpserver::~tcpserver () {loop_->assertinloopthread (); Log_trace << "Tcpserver::~tcpserver [" << name_ << "] destructing";}  The function multiple calls is harmless//The function can be called Across threads void Tcpserver::start () {if (!started_) {started_ = true; } if (!acceptor_->listenning()) {//Get_pointer returns the native pointer Loop_->runinloop (Boost::bind (&acceptor::listen, Get_pointer (ACCEPTOR_)));  }}void tcpserver::newconnection (int sockfd, const inetaddress& peeraddr) {loop_->assertinloopthread ();  Char buf[32];  snprintf (buf, sizeof buf, ":%s#%d", Hostport_.c_str (), nextconnid_);  ++nextconnid_;  String connname = Name_ + buf;           Log_info << "tcpserver::newconnection [" << name_ << "]-New Connection [" << Connname  << "] from" << peeraddr.toipport ();  InetAddress localaddr (Sockets::getlocaladdr (SOCKFD)); Fixme poll with zero timeout to double confirm the new connection//Fixme use make_shared if necessary tcpconnection                                          Ptr Conn (New Tcpconnection (Loop_, Connname,  SOCKFD, LOCALADDR, peeraddr));  CONNECTIONS_[CONNNAME] = conn; Conn->setconnectioncallback (Connectioncallback_);  Conn->setmessagecallback (Messagecallback_); Conn->connectestablished ();} </span>


test procedure:
#include <muduo/net/TcpServer.h> #include <muduo/net/EventLoop.h> #include <muduo/net/inetaddress.h > #include <stdio.h>using namespace muduo;using namespace muduo::net;void onConnection (const TCPCONNECTIONPTR               &conn) {if (conn->connected ()) {printf ("onConnection (): New connection [%s] from%s\n",    Conn->name (). C_STR (), conn->peeraddress (). Toipport (). C_STR ());    } else {printf ("onConnection (): Connection [%s] is down\n", Conn->name (). C_STR ()); }}void onMessage (const tcpconnectionptr &conn, const char *data, ssize_t len) {printf (" OnMessage (): Received%zd bytes from connection [%s]\n], Len, Conn->name (). C_STR ());}    int main () {printf ("main (): PID =%d\n", Getpid ());    InetAddress listenaddr (8888);    EventLoop Loop;    TCPServer Server (&loop, listenaddr, "testserver");    Server.setconnectioncallback (onConnection); server.seTmessagecallback (OnMessage);    Server.start (); Loop.loop ();}

Muduo Network Library Source Code Analysis (v) acceptor and TCPServer class

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.