time_wheel

time_wheel实际就是个时间轮定时器,时间轮定时器就不多解释了看下高性能服务编程那本书的时间轮定时器就ok了,muduo的时间轮只不过是时间轮定时器的可以说一部分吧,
这里的一开始初始化定时器的一轮tick的次数,因为主要就是针对每一个用户都是在相同的一定时间内没有再次访问的服务端需要断开与客户端连接,因此添加客户端连接信息的时候不必要添加定时时间,只需要当前tick的时的添加的,当轮到下一轮这个相同的位置就可以断开客户端(下面再介绍中途有请求的情况)
EchoServer::EchoServer(EventLoop* loop,
                       const InetAddress& listenAddr,
                       int idleSeconds)
  : server_(loop, listenAddr, "EchoServer"),
    connectionBuckets_(idleSeconds)
{
  connectionBuckets_.resize(idleSeconds);//设置时间轮的大小
}

typedef boost::shared_ptr EntryPtr;
typedef boost::weak_ptr WeakEntryPtr;
typedef boost::unordered_set Bucket;
typedef boost::circular_buffer WeakConnectionList;

muduo::net::TcpServer server_;
WeakConnectionList connectionBuckets_;

muduo没有自己去实现时间轮这个容器,而是使用boost库中的circular_buffer,这个用法我就不介绍了,随便找个链接吧http://www.cnblogs.com/TianFang/archive/2013/02/05/2892503.html
知道原理的话自己实现这个也是没啥问题的了

muduo的断开客户端判断是根据引用计数器到0自动断开,比如客户端第一次请求就是把引用计数器自增,而收到客户端的数据的时候就会把添加tick到的circular_buffer,这样引用计数器会加1,要是当以前的添加的位置,过一轮又回到那个位置,他的引用计数器就会减一下面就贴连接请求和接收收据的代码吧

```
void EchoServer::onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");

  if (conn->connected())
  {
    EntryPtr entry(new Entry(conn));
    connectionBuckets_.back().insert(entry);
    dumpConnectionBuckets();
    WeakEntryPtr weakEntry(entry);
    conn->setContext(weakEntry);
  }
  else
  {
    assert(!conn->getContext().empty());
    WeakEntryPtr weakEntry(boost::any_cast<WeakEntryPtr>(conn->getContext()));
    LOG_DEBUG << "Entry use_count = " << weakEntry.use_count();
  }
}
void EchoServer::onMessage(const TcpConnectionPtr& conn,
                           Buffer* buf,
                           Timestamp time)
{
  string msg(buf->retrieveAllAsString());
  LOG_INFO << conn->name() << " echo " << msg.size()
           << " bytes at " << time.toString();
  conn->send(msg);

  assert(!conn->getContext().empty());
  WeakEntryPtr weakEntry(boost::any_cast<WeakEntryPtr>(conn->getContext()));
  EntryPtr entry(weakEntry.lock());
  if (entry)
  {
    connectionBuckets_.back().insert(entry);

  }
}

在收到信息的时候需要把弱引用升级为强引用(就是muduo前面线程安全提到的棉线变铁丝)然后添加到容器中

你可能感兴趣的:(muduo-c++日记)