#include "examples/asio/chat/codec.h" #include "muduo/base/Logging.h" #include "muduo/base/Mutex.h" #include "muduo/net/EventLoop.h" #include "muduo/net/TcpServer.h" #include #include #include using namespace muduo; using namespace muduo::net; class ChatServer : noncopyable { public: ChatServer(EventLoop* loop, const InetAddress& listenAddr) : server_(loop, listenAddr, "ChatServer"), codec_(std::bind(&ChatServer::onStringMessage, this, _1, _2, _3)) { server_.setConnectionCallback( std::bind(&ChatServer::onConnection, this, _1)); server_.setMessageCallback( std::bind(&LengthHeaderCodec::onMessage, &codec_, _1, _2, _3)); } void setThreadNum(int numThreads) { server_.setThreadNum(numThreads); } void start() { server_.start(); } private: void onConnection(const TcpConnectionPtr& conn) { LOG_INFO << conn->localAddress().toIpPort() << " -> " << conn->peerAddress().toIpPort() << " is " << (conn->connected() ? "UP" : "DOWN"); MutexLockGuard lock(mutex_); if (conn->connected()) { connections_.insert(conn); } else { connections_.erase(conn); } } void onStringMessage(const TcpConnectionPtr&, const string& message, Timestamp) { MutexLockGuard lock(mutex_); for (ConnectionList::iterator it = connections_.begin(); it != connections_.end(); ++it) { codec_.send(get_pointer(*it), message); } } typedef std::set ConnectionList; TcpServer server_; LengthHeaderCodec codec_; MutexLock mutex_; ConnectionList connections_ GUARDED_BY(mutex_); }; int main(int argc, char* argv[]) { LOG_INFO << "pid = " << getpid(); if (argc > 1) { EventLoop loop; uint16_t port = static_cast(atoi(argv[1])); InetAddress serverAddr(port); ChatServer server(&loop, serverAddr); if (argc > 2) { server.setThreadNum(atoi(argv[2])); } server.start(); loop.loop(); } else { printf("Usage: %s port [thread_num]\n", argv[0]); } }