说明:
TcpServer.cc中客户端来一个连接的时候执行下面操作
TcpConnectionPtr conn(newTcpConnection(ioLoop,
connName,
sockfd,
localAddr,
peerAddr));
connections_[connName] = conn;
conn->setConnectionCallback(connectionCallback_);
conn->setMessageCallback(messageCallback_);
conn->setWriteCompleteCallback(writeCompleteCallback_);
conn->setCloseCallback(
boost::bind(&TcpServer::removeConnection,this, _1)); // FIXME: unsafe
ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished,conn));
即客户连接时候会调用TcpConnection::connectEstablished,该函数中会调用connectionCallback;
客户端关闭时候会调用TcpConnection::setConnectionCallback和 TcpConnection::setCloseCallback
typedef boost::weak_ptr<muduo::net::TcpConnection>WeakTcpConnectionPtr;
struct Entry : public muduo::copyable
{
/*初始化时候获得muduo::net::TcpConnection类型对象的弱指针*/
explicit Entry(const WeakTcpConnectionPtr& weakConn)
: weakConn_(weakConn)
{
}
/*析构时候将弱指针提升为强指针,提升成功则关闭写端*/
~Entry()
{
muduo::net::TcpConnectionPtr conn = weakConn_.lock();
if (conn)
{
conn->shutdown();
}
}
WeakTcpConnectionPtr weakConn_;
};
typedefboost::shared_ptr<TcpConnection> TcpConnectionPtr;
typedef boost::shared_ptr<Entry> EntryPtr;
typedef boost::weak_ptr<Entry> WeakEntryPtr;
typedef boost::unordered_set<EntryPtr>Bucket;
typedef boost::circular_buffer<Bucket>WeakConnectionList;
WeakConnectionListconnectionBuckets_; //存放连接的强指针
connectionBuckets是个循环队列,当往队尾插入一个元素空的Bucket时候,队头就会被删掉,此时队头的Bucket中每个EntryPtr的引用计数均会-1的,当该EntryPtr的引用计数值为0时候就会调用Entry对象的析构函数的。
说明:
最初connectionBuckets_.resize(idleSeconds);
当客户端连接上时候,客户的conn为TcpConnectionPtr;
EntryPtr entry(new Entry(conn)); //让强引用计数+1
connectionBuckets_.back().insert(entry); //将该强引用指针放入Bucket的末尾的set中
WeakEntryPtr weakEntry(entry); //将弱指针保存在conn中,如果将强指针存于conn 中则永远删不掉的
conn->setContext(weakEntry);
当收到客户端消息时候,
WeakEntryPtrweakEntry(boost::any_cast<WeakEntryPtr>(conn->getContext()));
EntryPtr entry(weakEntry.lock());
if (entry)
{
connectionBuckets_.back().insert(entry);
}
由于定时器1s会执行一次:
connectionBuckets_.push_back(Bucket());
这样会将队列的头部Bucket给弹出去的,即该Bucket中的每一个强引用计数-1,当减为0时候即调用~Entry(),这里面可以直接conn->shutdown();或者conn-> handleClose();