TcpClient类介绍[3-1]

来源:互联网 发布:java三层架构是哪三层 编辑:程序博客网 时间:2024/06/03 21:48

说明:

调用Connector类的start() ,新建socket非阻塞连接服务器;
调用Connector类的shutdown() ,关闭套接字的写管道;
调用Connector 类的stop() ,让epoll 不再关注套接字对应Channel 上的事件,将Channel从EPOLL类的channels_中移除,且从   epoll监听集合中移除;
TcpClient::newConnection中新建Socket以及对应的Channel,再将本层的函数
connectionCallback_/messageCallback_/writeCompleteCallback_注册给该Channel ;


TcpClient.h

#ifndef MUDUO_NET_TCPCLIENT_H
#define MUDUO_NET_TCPCLIENT_H


#include <boost/noncopyable.hpp>


#include <muduo/base/Mutex.h>
#include <muduo/net/TcpConnection.h>


namespace muduo
{
namespace net
{


class Connector;
typedef boost::shared_ptr<Connector> ConnectorPtr;


class TcpClient : boost::noncopyable
{
 public:
  // TcpClient(EventLoop* loop);
  // TcpClient(EventLoop* loop, const string& host, uint16_t port);
  TcpClient(EventLoop* loop,
            const InetAddress& serverAddr,
            const string& name);
  ~TcpClient();  // force out-line dtor, for scoped_ptr members.


  void connect();
  void disconnect();
  void stop();


  TcpConnectionPtr connection() const
  {
    MutexLockGuard lock(mutex_);
    return connection_;
  }


  EventLoop* getLoop() const { return loop_; }
  bool retry() const;
  void enableRetry() { retry_ = true; }


  /// Set connection callback.
  /// Not thread safe.
  void setConnectionCallback(const ConnectionCallback& cb)
  { connectionCallback_ = cb; }


  /// Set message callback.
  /// Not thread safe.
  void setMessageCallback(const MessageCallback& cb)
  { messageCallback_ = cb; }


  /// Set write complete callback.
  /// Not thread safe.
  void setWriteCompleteCallback(const WriteCompleteCallback& cb)
  { writeCompleteCallback_ = cb; }


 private:
  /// Not thread safe, but in loop
  void newConnection(int sockfd);
  /// Not thread safe, but in loop
  void removeConnection(const TcpConnectionPtr& conn);


  EventLoop* loop_;
  ConnectorPtr connector_; // avoid revealing Connector
  const string name_;
  ConnectionCallback connectionCallback_;
  MessageCallback messageCallback_;
  WriteCompleteCallback writeCompleteCallback_;
  bool retry_;   // atmoic
  bool connect_; // atomic
  // always in loop thread
  int nextConnId_;
  mutable MutexLock mutex_;
  TcpConnectionPtr connection_; // @BuardedBy mutex_
};


}
}


#endif  // MUDUO_NET_TCPCLIENT_H


TcpClient.cc

#include <muduo/net/TcpClient.h>


#include <muduo/base/Logging.h>
#include <muduo/net/Connector.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/SocketsOps.h>


#include <boost/bind.hpp>


#include <stdio.h>  // snprintf


using namespace muduo;
using namespace muduo::net;


// TcpClient::TcpClient(EventLoop* loop)
//   : loop_(loop)
// {
// }


// TcpClient::TcpClient(EventLoop* loop, const string& host, uint16_t port)
//   : loop_(CHECK_NOTNULL(loop)),
//     serverAddr_(host, port)
// {
// }


namespace muduo
{
namespace net
{
namespace detail
{


void removeConnection(EventLoop* loop, const TcpConnectionPtr& conn)
{
 loop->queueInLoop(boost::bind(&TcpConnection::connectDestroyed, conn));
}


void removeConnector(const ConnectorPtr& connector)
{
 //connector->
}


}
}
}




/*
初始化要连接的服务器的addr
*/
TcpClient::TcpClient(EventLoop* loop,
                     const InetAddress& serverAddr,
                     const string& name)
  : loop_(CHECK_NOTNULL(loop)),
    connector_(new Connector(loop, serverAddr)),
    name_(name),
    connectionCallback_(defaultConnectionCallback),
    messageCallback_(defaultMessageCallback),
    retry_(false),
    connect_(true),
    nextConnId_(1)
{
 connector_->setNewConnectionCallback(
     boost::bind(&TcpClient::newConnection, this, _1));
 // FIXME setConnectFailedCallback
 LOG_INFO << "TcpClient::TcpClient[" << name_
          << "] - connector " << get_pointer(connector_);
}


TcpClient::~TcpClient()
{
 LOG_INFO << "TcpClient::~TcpClient[" << name_
          << "] - connector " << get_pointer(connector_);
 TcpConnectionPtr conn;
 {
   MutexLockGuard lock(mutex_);
   conn = connection_;
 }
 if (conn)
 {
   // FIXME: not 100% safe, if we are in different thread
   CloseCallback cb = boost::bind(&detail::removeConnection, loop_, _1);
   loop_->runInLoop(
       boost::bind(&TcpConnection::setCloseCallback, conn, cb));
 }
 else
 {
   connector_->stop();
   // FIXME: HACK
   loop_->runAfter(1, boost::bind(&detail::removeConnector, connector_));
 }
}




/*
调用Connector 类的start() ,新建socket 非阻塞连接服务器
*/
void TcpClient::connect()
{
 // FIXME: check state
 LOG_INFO << "TcpClient::connect[" << name_ << "] - connecting to "
          << connector_->serverAddress().toIpPort();
 connect_ = true;
 connector_->start();
}




/*
调用Connector 类的shutdown() ,关闭套接字的写管道
*/
void TcpClient::disconnect()
{
 connect_ = false;


 {
   MutexLockGuard lock(mutex_);
   if (connection_)
   {
     connection_->shutdown();
   }
 }
}




/*
调用Connector 类的stop() ,
让epoll 不再关注套接字对应Channel 上的事件;
将Channel 从EPOLL类的channels_ 中移除,且从epoll监听集合中移除;

*/
void TcpClient::stop()
{
 connect_ = false;
 connector_->stop();
}




/*
new TcpConnection 即新建Socket以及对应的Channel,
再将本层的函数connectionCallback_/messageCallback_/writeCompleteCallback_
注册给该Channel ;

*/
void TcpClient::newConnection(int sockfd)
{
 loop_->assertInLoopThread();
 InetAddress peerAddr(sockets::getPeerAddr(sockfd));
 char buf[32];
 snprintf(buf, sizeof buf, ":%s#%d", peerAddr.toIpPort().c_str(), nextConnId_);
 ++nextConnId_;
 string connName = name_ + buf;


 InetAddress localAddr(sockets::getLocalAddr(sockfd));
 // FIXME poll with zero timeout to double confirm the new connection
 // FIXME use make_shared if necessary
 TcpConnectionPtr conn(new TcpConnection(loop_,
                                         connName,
                                         sockfd,
                                         localAddr,
                                         peerAddr));


 conn->setConnectionCallback(connectionCallback_);
 conn->setMessageCallback(messageCallback_);
 conn->setWriteCompleteCallback(writeCompleteCallback_);
 conn->setCloseCallback(
     boost::bind(&TcpClient::removeConnection, this, _1)); // FIXME: unsafe
 {
   MutexLockGuard lock(mutex_);
   connection_ = conn;
 }
 conn->connectEstablished();
}




/*
TcpConnection::connectDestroyed里面即会调用
TcpClient::connectionCallback_函数

*/
void TcpClient::removeConnection(const TcpConnectionPtr& conn)
{
 loop_->assertInLoopThread();
 assert(loop_ == conn->getLoop());


 {
   MutexLockGuard lock(mutex_);
   assert(connection_ == conn);
   connection_.reset();
 }


 loop_->queueInLoop(boost::bind(&TcpConnection::connectDestroyed, conn));
 if (retry_ && connect_)
 {
   LOG_INFO << "TcpClient::connect[" << name_ << "] - Reconnecting to "
            << connector_->serverAddress().toIpPort();
   connector_->restart();
 }
}

0 0
原创粉丝点击