muduo用TcpClient发起连接,TcpClient有一个Connector连接器,TCPClient使用Conneccor发起连接, 连接建立成功后, 用socket创建TcpConnection来管理连接, 每个TcpClient class只管理一个TcpConnecction,连接建立成功后设置相应的回调函数。很显然,TcpClient用来管理客户端连接,真正连接交给Connector。

TcpClient.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 a public header file, it must only include public header files.#ifndef MUDUO_NET_TCPCLIENT_H
#define MUDUO_NET_TCPCLIENT_H#include "muduo/base/Mutex.h"
#include "muduo/net/TcpConnection.h"namespace muduo
{
namespace net
{class Connector;
typedef std::shared_ptr<Connector> ConnectorPtr;//TCPClient使用Conneccor发起连接, 连接建立成功后, 用socket创建TcpConnection来管理连接, 每个TcpClient class只管理一个TcpConnecction
class TcpClient : noncopyable
{public:// TcpClient(EventLoop* loop);// TcpClient(EventLoop* loop, const string& host, uint16_t port);TcpClient(EventLoop* loop,const InetAddress& serverAddr,const string& nameArg);~TcpClient();  // force out-line dtor, for std::unique_ptr members.void connect();void disconnect();void stop();TcpConnectionPtr connection() const{MutexLockGuard lock(mutex_);return connection_;}EventLoop* getLoop() const { return loop_; }bool retry() const { return retry_; }void enableRetry() { retry_ = true; }const string& name() const{ return name_; }/// Set connection callback./// Not thread safe.void setConnectionCallback(ConnectionCallback cb){ connectionCallback_ = std::move(cb); }/// Set message callback./// Not thread safe.void setMessageCallback(MessageCallback cb){ messageCallback_ = std::move(cb); }/// Set write complete callback./// Not thread safe.void setWriteCompleteCallback(WriteCompleteCallback cb){ writeCompleteCallback_ = std::move(cb); }private:/// Not thread safe, but in loopvoid newConnection(int sockfd);/// Not thread safe, but in loopvoid removeConnection(const TcpConnectionPtr& conn);EventLoop* loop_;             //用户创建传入的EventLoopConnectorPtr connector_; // avoid revealing Connector //指向Connector的shared_ptrconst string name_;         //用户指定的名字//这些回调函数都需要显示设置ConnectionCallback connectionCallback_;         //连接建立回调函数MessageCallback messageCallback_;                 //消息到来回调函数WriteCompleteCallback writeCompleteCallback_;     //数据发送完毕回调函数    bool retry_;   // atomic            //连接断开后是否重连bool connect_; // atomic// always in loop threadint nextConnId_;             //name_+nextConnId_用于标识一个连接mutable MutexLock mutex_;TcpConnectionPtr connection_ GUARDED_BY(mutex_);
};}  // namespace net
}  // namespace muduo#endif  // MUDUO_NET_TCPCLIENT_H

TcpClient.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/TcpClient.h"#include "muduo/base/Logging.h"
#include "muduo/net/Connector.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/SocketsOps.h"#include <stdio.h>  // snprintfusing 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(std::bind(&TcpConnection::connectDestroyed, conn));
}void removeConnector(const ConnectorPtr& connector)
{//connector->
}}  // namespace detail
}  // namespace net
}  // namespace muduoTcpClient::TcpClient(EventLoop* loop,const InetAddress& serverAddr,const string& nameArg): loop_(CHECK_NOTNULL(loop)),connector_(new Connector(loop, serverAddr)),name_(nameArg),connectionCallback_(defaultConnectionCallback),messageCallback_(defaultMessageCallback),retry_(false),connect_(true),nextConnId_(1)
{//将Connector的连接回调函数设置为TcpClient::newConnection//该函数在Connector::handleWrite中被调用connector_->setNewConnectionCallback(std::bind(&TcpClient::newConnection, this, _1));// FIXME setConnectFailedCallbackLOG_INFO << "TcpClient::TcpClient[" << name_<< "] - connector " << get_pointer(connector_);
}TcpClient::~TcpClient()
{LOG_INFO << "TcpClient::~TcpClient[" << name_<< "] - connector " << get_pointer(connector_);TcpConnectionPtr conn;bool unique = false;{MutexLockGuard lock(mutex_);unique = connection_.unique();conn = connection_;}if (conn){assert(loop_ == conn->getLoop());// FIXME: not 100% safe, if we are in different threadCloseCallback cb = std::bind(&detail::removeConnection, loop_, _1);loop_->runInLoop(std::bind(&TcpConnection::setCloseCallback, conn, cb));if (unique){conn->forceClose();}}else{connector_->stop();// FIXME: HACKloop_->runAfter(1, std::bind(&detail::removeConnector, connector_));}
}void TcpClient::connect()
{// FIXME: check stateLOG_INFO << "TcpClient::connect[" << name_ << "] - connecting to "<< connector_->serverAddress().toIpPort();connect_ = true;//调用Connector::start,发起连接connector_->start();
}void TcpClient::disconnect()
{connect_ = false;{MutexLockGuard lock(mutex_);if (connection_){connection_->shutdown();}}
}void TcpClient::stop()
{connect_ = false;connector_->stop();
}//新连接的回调函数,将新连接封装为TcpConnection交给TcpClient来管理
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//创建一个堆上局部TcpConnection对象,并用TcpClient的智能指针connection_保存起来TcpConnectionPtr conn(new TcpConnection(loop_,connName,sockfd,localAddr,peerAddr));//设置各种回调函数conn->setConnectionCallback(connectionCallback_);         //连接建立conn->setMessageCallback(messageCallback_);                //可读conn->setWriteCompleteCallback(writeCompleteCallback_);  //可写conn->setCloseCallback(std::bind(&TcpClient::removeConnection, this, _1)); // FIXME: unsafe{MutexLockGuard lock(mutex_);//将新创建的TcpConnection赋给TcpClient类内成员connection_connection_ = conn;}conn->connectEstablished();
}void TcpClient::removeConnection(const TcpConnectionPtr& conn)
{loop_->assertInLoopThread();assert(loop_ == conn->getLoop());{MutexLockGuard lock(mutex_);assert(connection_ == conn);connection_.reset();       //重置}//I/O线程中销毁loop_->queueInLoop(std::bind(&TcpConnection::connectDestroyed, conn));if (retry_ && connect_)     //是否发起重连{LOG_INFO << "TcpClient::connect[" << name_ << "] - Reconnecting to "<< connector_->serverAddress().toIpPort();//这里的重连是连接成功后断开的重连,所以实际上是重启connector_->restart();}
}

muduo之TcpClient相关推荐

  1. 学习Muduo中ChatRoom实现的各种细节和思考

    Muduo中ChatRoom 1.长连接中的分包解决 固定消息长度, 比如说固定消息长度是16字节 使用特殊的字符作为分割符号,比如说 HTTP协议中的\r\n作为头部的分割符 每个消息头部加上长度字 ...

  2. net12. 客户类——TcpClient

    TcpClient类 muduo用TcpClient发起连接,TcpClient有一个Connector连接器,TCPClient使用Connector发起连接, 连接建立成功后, 用socket创建 ...

  3. 客户端压测server端计算qps以及不同延迟时间下响应数量所占百分比

    将时间戳转为时间显示 date -d @978278400 percentile.h https://github.com/chenshuo/muduo/blob/master/examples/su ...

  4. 46muduo库使用示例(五)

    1.RTT计算 2.代码 #include <muduo/base/Logging.h> #include <muduo/net/EventLoop.h> #include & ...

  5. muduo之Connector

    Connector负责主动发起连接,不负责创建socket,只负责连接的建立,外部调用Connector::start就可以发起连接,Connector具有重连的功能和停止连接的功能,连接成功建立后返 ...

  6. muduo网络库源码阅读Step by Step

    Posted on: Nov 26 2015 Categories: muduo C++ Tags: muduo 一般写服务端程序都需要有一个称手的网络库来帮我们处理琐碎的网络通信细节,比如连接的建立 ...

  7. Muduo网络库核心梳理

    Muduo网络库 Muduo网络库本身并不复杂,是一个新手入门C++面向对象网络编程的经典实战项目.但是,新手在刚刚上手读代码的时候,非常容易陷入代码的汪洋大海,迷失方向.本文旨在简要梳理Muduo网 ...

  8. 陈硕Muduo网络库--功能架构总结

    Muduo的事件循环/线程池/客户端/服务端/Io复用总结: 1.一个EventLoop的loop独占一个线程 EventLoop本身构成了此线程执行的语境 2.利用EventLoop内的epoll描 ...

  9. muduo网络库学习总结:基本架构及流程分析

    muduo网络库学习:基本架构及流程分析 基本架构 Basic Reactor Mutiple Reactor + ThreadPool muduo库的基本使用 基本结构介绍 EventLoop类 P ...

最新文章

  1. [导入]实时数据库的经典书
  2. 第 22 章 DDL - Data Definition Language
  3. 使用运行时动态创建属性
  4. Session会话技术
  5. 想让AI在企业落地?微软最新Azure AI不容错过!
  6. 优化搜索排序结果从而“ 提升CTR、CVR业务指标”
  7. [java理论篇]--java的面向对象
  8. 怎么用wifi进e站_忘记wifi密码怎么办,用这招可以知道电脑中的wifi密码
  9. C/C++函数调用方式
  10. moss form验证 配置文件关键部分
  11. Git客户端操作GitHub
  12. R语言 在R中实现vlookup的功能
  13. Python基础知识-pycharm版 第3节
  14. Typora 自定义快捷键
  15. python 基础词汇及其应用1
  16. python 爬取bilibili番剧排行榜
  17. 正则表达式 1-100的整数
  18. 数据结构:顺序栈基本操作(入栈和出栈)C语言详解(转载)by解学武
  19. 为什么有些公司不让用 Lombok ?
  20. 聊一聊深度学习以往那些关于CNN和RNN的事

热门文章

  1. 【数据挖掘】K-Means 二维数据聚类分析 ( K-Means 迭代总结 | K-Means 初始中心点选择方案 | K-Means 算法优缺点 | K-Means 算法变种 )
  2. 邂逅 2008-06-27 23:24
  3. 1003 Dijkstra算法
  4. Bugku——Web——矛盾
  5. Jenkins结合.net平台工具之Nunit
  6. 加了try的情况下线程中抛出未捕获的异常
  7. java怎么删除List中的指定元素
  8. hdu2036(多边形面积)
  9. (笔试题)小米Git
  10. DEDECMS模块插件制作举例-模块生成向导