#include "examples/idleconnection/echo.h" #include "muduo/base/Logging.h" #include "muduo/net/EventLoop.h" #include #include using namespace muduo; using namespace muduo::net; EchoServer::EchoServer(EventLoop* loop, const InetAddress& listenAddr, int idleSeconds) : server_(loop, listenAddr, "EchoServer"), connectionBuckets_(idleSeconds) { server_.setConnectionCallback( std::bind(&EchoServer::onConnection, this, _1)); server_.setMessageCallback( std::bind(&EchoServer::onMessage, this, _1, _2, _3)); loop->runEvery(1.0, std::bind(&EchoServer::onTimer, this)); connectionBuckets_.resize(idleSeconds); dumpConnectionBuckets(); } void EchoServer::start() { server_.start(); } 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(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(conn->getContext())); EntryPtr entry(weakEntry.lock()); if (entry) { connectionBuckets_.back().insert(entry); dumpConnectionBuckets(); } } void EchoServer::onTimer() { connectionBuckets_.push_back(Bucket()); dumpConnectionBuckets(); } void EchoServer::dumpConnectionBuckets() const { LOG_INFO << "size = " << connectionBuckets_.size(); int idx = 0; for (WeakConnectionList::const_iterator bucketI = connectionBuckets_.begin(); bucketI != connectionBuckets_.end(); ++bucketI, ++idx) { const Bucket& bucket = *bucketI; printf("[%d] len = %zd : ", idx, bucket.size()); for (const auto& it : bucket) { bool connectionDead = it->weakConn_.expired(); printf("%p(%ld)%s, ", get_pointer(it), it.use_count(), connectionDead ? " DEAD" : ""); } puts(""); } }