TcpClient类

  1. muduo用TcpClient发起连接,TcpClient有一个Connector连接器,TCPClient使用Connector发起连接, 连接建立成功后, 用socket创建TcpConnection来管理连接, 每个TcpClientclass只管理一个TcpConnecction,连接建立成功后设置相应的回调函数。很显然,TcpClient用来管理客户端连接,真正连接交给Connector。
  2. TcpClient具备TcpConnection断开之后重新连接的功能,加上Connector具备反复尝试连接的功能,因此客户端和服务器的启动顺序无关紧要。可以先启动客户端,一旦服务器启动,半分钟之内即可恢复连接(由Connector::kMaxRetryDelayMs常数控制);再客户端运行期间服务器可以重启,客户端也会自动重连。
  3. 连接断开后初次重试的延迟时间是随机的,比方说服务器崩溃,它所有的客户端连接同时断开,然后0.5s之后同时再次发起连接,这样既可能造成SYN丢包,也可能给服务器带来短期大负载,影响其服务质量。因此每个TcpClient应该等待一段随机的时间(0.5~2s),再充实,避免拥塞。
  4. 发起连接的时候如果发生TCP SYN丢包,那么系统默认的重试间隔是3s,这期间不会返回错误码,而且这个间隔似乎不容易修改。如果需要缩短间隔,可以再用一个定时器,在0.5s或1s之后发起另一个链接。如果有需求的话,这个功能可以做到Connector中

数据成员:

EventLoop* loop_:所属EventLoop
ConnectorPtr connector_:connector_用于主动发起连接
size_t writerIndex_:写位置
const string name_:名称
ConnectionCallback connectionCallback_:连接建立成功时的回调函数
MessageCallback messageCallback_:消息到来时的回调函数
WriteCompleteCallback writeCompleteCallback_:数据发送完毕时的回调函数
bool retry_:是否重连,是指连接建立之后又断开的时候是否重连
bool connect_:是否连接
int nextConnId_:下一个连接的ID,name_ + nextConnId_用于标识一个连接
mutable MutexLock mutex_:互斥量mutex_
TcpConnectionPtr connection_:Connector连接成功以后,得到一个TcpConnection类型的connection_

成员函数:

TcpClient(EventLoop* loop, const InetAddress& serverAddr,const string& name):构造函数
~TcpClient():析构函数
void connect():发起连接
void disconnect():用于连接已建立的情况下,关闭连接
void stop():连接尚未建立成功,停止发起连接
TcpConnectionPtr connection() const:没有用到此函数
bool retry() const:没有用到此函数
void enableRetry():设置连接处于重连的状态,retry_=true
void setConnectionCallback(const ConnectionCallback& cb):注册连接建立成功时回调的函数
void setMessageCallback(const MessageCallback& cb):注册消息到来时的回调函数
void setWriteCompleteCallback(const WriteCompleteCallback& cb):注册数据发送完毕时的回调函数
void newConnection(int sockfd):连接建立成功时回调的函数
void removeConnection(const TcpConnectionPtr& conn):连接断开时回调的函数

TcpClient.h

// This is a public header file, it must only include public header files.
//包含一个Connector对象
#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_;}//没有用到此函数bool retry() const;//设置连接处于重连的状态,retry_=truevoid 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);//所属EventLoopEventLoop* loop_;//connector_用于主动发起连接ConnectorPtr connector_;   //名称const string name_;//连接建立成功时的回调函数ConnectionCallback connectionCallback_;        //消息到来时的回调函数MessageCallback messageCallback_;               //数据发送完毕时的回调函数WriteCompleteCallback writeCompleteCallback_; //是否重连,是指连接建立之后又断开的时候是否重连bool retry_;   //是否连接bool connect_; // atomic//always in loop thread//下一个连接的ID,name_ + nextConnId_用于标识一个连接int nextConnId_;          //互斥量mutex_mutable MutexLock mutex_;//Connector连接成功以后,得到一个TcpConnection类型的connection_TcpConnectionPtr connection_;
};}
}#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>  // 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(boost::bind(&TcpConnection::connectDestroyed, conn));
}void removeConnector(const ConnectorPtr& connector)
{//connector->
}}
}
}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 setConnectFailedCallbackLOG_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// 重新设置TcpConnection中的closeCallback_为detail::removeConnectionCloseCallback cb = boost::bind(&detail::removeConnection, loop_, _1);loop_->runInLoop(boost::bind(&TcpConnection::setCloseCallback, conn, cb));}else{// 这种情况,说明connector处于未连接状态,将connector_停止connector_->stop();// FIXME: HACKloop_->runAfter(1, boost::bind(&detail::removeConnector, connector_));}
}void TcpClient::connect()
{// FIXME: check stateLOG_INFO << "TcpClient::connect[" << name_ << "] - connecting to "<< connector_->serverAddress().toIpPort();connect_ = true;connector_->start();   // 发起连接
}// 用于连接已建立的情况下,关闭连接
void TcpClient::disconnect()
{connect_ = false;{MutexLockGuard lock(mutex_);if (connection_){connection_->shutdown();}}
}// 停止connector_
void TcpClient::stop()
{connect_ = false;connector_->stop();
}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 necessaryTcpConnectionPtr 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;      // 保存TcpConnection}conn->connectEstablished();       // 这里回调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();}
}

net12. 客户类——TcpClient相关推荐

  1. 定义客户类 客户积分回馈

    需求说明: 编写客户类 属性:积分integralCount.卡类型 cardType(金卡.普卡) 方法:show(),显示客户信息 实现积分回馈功能,金卡客户积分大于1000分或普卡客户积分大于5 ...

  2. java第十四章上机四客户类_java语言程序设计教学大纲.doc

    java语言程序设计教学大纲.doc 还剩 5页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: 第六章 结构控制 2 2第七章 数组 2第八章 字符串 ...

  3. TCPClient、TCPListener的用法

    支持Http.Tcp和Udp的类组成了TCP/IP三层模型(请求响应层.应用协议层.传输层)的中间层-应用协议层,该层的类比位于最底层的Socket类提供了更高层次的抽象,它们封装 TCP 和 UDP ...

  4. 五分钟看懂UML类图与类的关系详解

    在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分为 ...

  5. UML类图与类的关系详解

    UML类图与类的关系详解   2011-04-21 来源:网络   在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(D ...

  6. C++设计模式——适配器模式(对象适配器、类适配器)

    http://blog.jobbole.com/109381/?winzoom=1 前言 现在的笔记本都只存在USB接口,用来口,电脑上存在的是USB接口,两者如何通信呢?可以使用USB转串口线连接电 ...

  7. 【UML 建模】UML建模语言入门 -- 静态图详解 类图 对象图 包图 静态图建模实战

    发现个好东西思维导图, 最近开始用MindManager整理博客 . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/deta ...

  8. 适配器模式——类适配器模式,对象适配器模式

    概述 如果去欧洲国家去旅游的话,他们的插座如下图最左边,是欧洲标准. 而我们使用的插头如下图最右边的.因此我们的笔记本电脑,手机在当地不能直接充电. 所以就需要一个插座转换器,转换器第1面插入当地的插 ...

  9. UML类图与类的关系详解【转】

    在画类图的时候,理清类和类之间的关系是重点. 类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分 ...

最新文章

  1. Leangoo看板Jenkins配置指南
  2. linux查看特定文件的位置
  3. 推荐 8 个常用 Spring Boot 项目
  4. 数学狂想曲(十)——复变函数, 平稳离散时间随机过程, 功率谱
  5. SAP ABAP编辑器里的Code Completion(代码自动完成)的等待时间设置
  6. maven使用testng_使用ReportNG更好看的TestNG HTML测试报告– Maven指南
  7. MyBatis初级入门及常见问题
  8. 基于MATLAB的Sobel边缘检测算法实现
  9. NSInvocation的一种用法
  10. 线性代数【五】向量(2):向量组的秩,向量内积、正交,正交规范化,向量空间
  11. jmeter录制脚本(Mac)
  12. 鸿蒙DevEco Studio 无法下载Gradle问题
  13. GitHub哔哩哔哩(bilibili)高清视频下载
  14. python画爱心的代码怎么运行_怎么用python实现画爱心
  15. 一、Linux 教程-基础
  16. 李峋爱心Python代码
  17. gitee生成公钥报错
  18. Tree Map:树状图——绘制COVID-19阵列图
  19. https双向认证访问管理后台,采用USBKEY进行系统访问的身份鉴别,KEY的证书长度大于128位,使用USBKEY登录
  20. 使用meb工具在线热备,将单实例切换为主从

热门文章

  1. 多接口扩展坞加充电宝方案
  2. java常见抛错之NullPointException抛错分析
  3. IDEA翻译插件Translation的安装,百度翻译的应用ID和秘钥申请详细步骤
  4. java jvm优化(一)
  5. 远程办公得力助手企业云盘
  6. 已用上MIX 4,雷军回顾MIX系列过去5款机型
  7. 解决方案:uni-app非nvue模式下切换主题后,App端闪屏、闪白、闪黑、状态栏主题色不稳定
  8. 率先布局 RWA 赛道,PoseiSwap 成为最具先进性的 DEX
  9. 《汽车行业面向智能制造的BOM物料管理》拆书心得—第二章 转型期需要什么样的BOM体系
  10. 磕磕绊绊的双非硕秋招之路小结