muduo库阅读(42)——Net部分:TCP客户端TcpClient
来源:互联网 发布:骨朵网络影视数据 编辑:程序博客网 时间:2024/06/04 19:39
TcpClient的工作流程如下:
1、根据构造函数传递进来的EventLoop和服务器地址等信息进行初始化
2、建立一个连接器Connector
3、设置连接器的事件处理器的写事件回调函数为newConnection(当连接建立完成的时候会触发写事件,Connector的事件处理进行处理,并调用写事件的回调函数)
4、调用connect向对服务器进行连接,内部调用连接器的start函数,然后等待连接完成
5、连接建立完成的时候会触发写事件,Connector的事件处理进行处理,并调用写事件的回调函数ewConnection
5.1、设置新链接的id和名字
5.2、创建一个TcpConnection对象
5.3、设置TcpConnection对象的回调函数:用户的连接建立回调函数、用户的数据到来回调函数、用户的写完成回调函数
5.4、调用TcpConnection的connectEstablished函数表示连接建立完毕
1、根据构造函数传递进来的EventLoop和服务器地址等信息进行初始化
2、建立一个连接器Connector
3、设置连接器的事件处理器的写事件回调函数为newConnection(当连接建立完成的时候会触发写事件,Connector的事件处理进行处理,并调用写事件的回调函数)
4、调用connect向对服务器进行连接,内部调用连接器的start函数,然后等待连接完成
5、连接建立完成的时候会触发写事件,Connector的事件处理进行处理,并调用写事件的回调函数ewConnection
5.1、设置新链接的id和名字
5.2、创建一个TcpConnection对象
5.3、设置TcpConnection对象的回调函数:用户的连接建立回调函数、用户的数据到来回调函数、用户的写完成回调函数
5.4、调用TcpConnection的connectEstablished函数表示连接建立完毕
/* * tcp客户端 */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& nameArg);~TcpClient(); // force out-line dtor, for scoped_ptr members.// 连接void connect();// 断开连接void disconnect();// 停止连接void stop();// 返回TcpConnection对象TcpConnectionPtr connection() const{MutexLockGuard lock(mutex_);return connection_;}// 获取所属的ReactorEventLoop* getLoop() const { return loop_; }// 重连bool retry() const;// 允许重连void enableRetry() { retry_ = true; }// 获取名字const string& name() const{ return name_; }// 设置连接完成的回调函数void setConnectionCallback(const ConnectionCallback& cb){ connectionCallback_ = cb; }// 设置数据到来的回调函数void setMessageCallback(const MessageCallback& cb){ messageCallback_ = cb; }// 设置写完成的回调函数void setWriteCompleteCallback(const WriteCompleteCallback& cb){ writeCompleteCallback_ = cb; }#ifdef __GXX_EXPERIMENTAL_CXX0X__void setConnectionCallback(ConnectionCallback&& cb){ connectionCallback_ = std::move(cb); }void setMessageCallback(MessageCallback&& cb){ messageCallback_ = std::move(cb); }void setWriteCompleteCallback(WriteCompleteCallback&& cb){ writeCompleteCallback_ = std::move(cb); }#endifprivate:// 连接建立完毕会调用这个函数void newConnection(int sockfd);// 移除一个链接void removeConnection(const TcpConnectionPtr& conn);// 所属的ReactorEventLoop* loop_;// 连接器ConnectorPtr connector_; // avoid revealing Connector// 名字const string name_;// 连接建立完成的回调函数ConnectionCallback connectionCallback_;// 数据到来回调函数MessageCallback messageCallback_;// 写完成回调函数WriteCompleteCallback writeCompleteCallback_;// 是否重试bool retry_; // atomic// 是否已经建立连接bool connect_; // atomic// always in loop thread// TcpConnection的idint nextConnId_;// 锁mutable MutexLock mutex_;// 客户端到服务器的连接TcpConnectionPtr connection_; // @GuardedBy mutex_};}}
using namespace muduo;using namespace muduo::net;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& nameArg): loop_(CHECK_NOTNULL(loop)), connector_(new Connector(loop, serverAddr)),// 创建一个连接器 name_(nameArg), 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;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 thread// 移除TcpConnection对象CloseCallback cb = boost::bind(&detail::removeConnection, loop_, _1);// 调用链接关闭回调函数loop_->runInLoop(boost::bind(&TcpConnection::setCloseCallback, conn, cb));if (unique){// 强制关闭conn->forceClose();}}else{// 停止连接器connector_->stop();// FIXME: HACK// 移除连接器loop_->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();}}}// 停止连接void TcpClient::stop(){connect_ = false;// 停止连接器connector_->stop();}// 连接建立完成的回调函数// 连接器连接到服务器的时候会触发写事件,然后事件处理器处理写事件,调用处理写事件的回调函数,这个回调函数就是newConnectionvoid TcpClient::newConnection(int sockfd){loop_->assertInLoopThread();// 获取远端地址(即服务器的地址)InetAddress peerAddr(sockets::getPeerAddr(sockfd));// 设置新连接的id和名字char buf[32];snprintf(buf, sizeof buf, ":%s#%d", peerAddr.toIpPort().c_str(), nextConnId_);++nextConnId_;string connName = name_ + buf;InetAddress localAddr(sockets::getLocalAddr(sockfd));// 创建一个TcpConnection对象TcpConnectionPtr conn(new TcpConnection(loop_,connName,sockfd,localAddr,peerAddr));// 设置TcpConnection对象的用户回调函数,因为用户直接使用TcpConnection来进行数据读写操作// 设置用户的连接建立完成回调函数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的connectEstablished函数表示链接建立conn->connectEstablished();}// 移除连接void TcpClient::removeConnection(const TcpConnectionPtr& conn){loop_->assertInLoopThread();assert(loop_ == conn->getLoop());{MutexLockGuard lock(mutex_);assert(connection_ == conn);connection_.reset();}// 调用TcpConnection::connectDestroyed销毁连接loop_->queueInLoop(boost::bind(&TcpConnection::connectDestroyed, conn));// 如果可以重连并且已经建立连接,那么进行重连if (retry_ && connect_){LOG_INFO << "TcpClient::connect[" << name_ << "] - Reconnecting to "<< connector_->serverAddress().toIpPort();connector_->restart();}}
0 0
- muduo库阅读(42)——Net部分:TCP客户端TcpClient
- muduo库阅读(38)——Net部分:TCP连接TcpConnection
- muduo库阅读(40)——Net部分:TCP服务器TcpServer
- muduo库阅读(43)——Net部分:轮询器的epoll实现——EPollPoller
- muduo库阅读(29)——Net部分:Reactor(EventLoop事件循环)
- muduo库阅读(31)——Net部分:定时器(计时器)Timer
- muduo库阅读(32)——Net部分:定时器(计时器)ID类TimerId
- muduo库阅读(23)——Net部分:应用层缓冲区类
- muduo库阅读(24)——Net部分:网络地址类
- muduo库阅读(25)——Net部分:服务器端的套接字类
- muduo库阅读(26)——Net部分:套接字常用操作的封装
- muduo库阅读(27)——Net部分:字节顺序转换的封装
- muduo库阅读(28)——Net部分:各类回调函数的定义
- muduo库阅读(30)——Net部分:事件处理器Channel
- muduo库阅读(33)——Net部分:定时器队列TimerQueue
- muduo库阅读(34)——Net部分:轮询器基类Poller
- muduo库阅读(36)——Net部分:事件循环线程池EventLoopThreadPool
- muduo库阅读(37)——Net部分:压缩数据流ZlibOutputStream
- GCD的介绍和使用(五)
- 关于Unity3d中的LayerMask使用
- DOM(文档对象模型)解析原理
- 转意字符问题
- linux/windows下开发yii项目
- muduo库阅读(42)——Net部分:TCP客户端TcpClient
- 全面了解docker,赢在精彩问答中!
- xmpp
- 坑爹的golang日期时间格式format()
- 认识json(JavaScript 对象表示法)
- Elasticsearch Query String Query
- 通过RS232发送和接收短信(三)
- 插入排序—直接插入
- 【Java并发编程】之五:volatile变量修饰符—意料之外的问题(含代码)