1.基本概念
Muduo
由陈硕大佬开发,是一个基于非阻塞IO 和事件驱动 的C++高并发TCP网络编程库 。它是一款基于主从Reactor 模型的网络库,其使用的线程模型是 one loop per thread。
1.1 主从 Reactor 模型
- 主 Reactor (
MainReactor
,通常由EventLoop
实现):- 负责监听新连接(
accept
事件),通过Acceptor
类实现。 - 使用
epoll
/poll
等多路复用机制监控监听套接字。
- 负责监听新连接(
- 从 Reactor (
SubReactor
,多个EventLoop
线程):- 每个
EventLoop
管理一组已建立的 TCP 连接(TcpConnection
)。 - 处理连接的读写事件、定时任务和用户回调。
- 每个
1.2 One Loop Per Thread
- 线程绑定 :每个
EventLoop
对象严格绑定到一个线程(通过EventLoop::loop()
在所属线程运行)。 - 资源隔离 :TCP 连接的生命周期由所属
EventLoop
管理,避免跨线程竞争。 - 性能优化 :通过线程局部存储(
ThreadLocal
)实现高效的事件循环访问。

2.常见接口
2.1TcpServer 类基础介绍
Kotlin
typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;
typedef std::function<void (const TcpConnectionPtr&)> ConnectionCallback;
typedef std::function<void (const TcpConnectionPtr&, Buffer*, Timestamp)> MessageCallback;
class InetAddress : public muduo::copyable
{
public:
InetAddress(StringArg ip, uint16_t port, bool ipv6 = false);
};
class TcpServer : noncopyable
{
public:
enum Option
{
kNoReusePort,
kReusePort,
};
TcpServer(EventLoop* loop, const InetAddress& listenAddr, const string& nameArg, Option option = kNoReusePort);
void setThreadNum(int numThreads);
void start();
// 当⼀个新连接建⽴成功的时候被调用
void setConnectionCallback(const ConnectionCallback& cb)
{ connectionCallback_ = cb; }
// 消息的业务处理回调函数---这是收到新连接消息的时候被调用的函数
void setMessageCallback(const MessageCallback& cb)
{ messageCallback_ = cb; }
};
-
职责:服务端入口,管理监听套接字和连接池。
-
关键流程:
- 构造时绑定
EventLoop
(主 Reactor)。 start()
启动监听,注册Acceptor
到主 Reactor。- 新连接到达时,通过轮询算法分配从 Reactor 管理。
- 构造时绑定
TcpServer(EventLoop* loop, const InetAddress& listenAddr, const string& nameArg)
:构造函数,loop
是事件循环对象,listenAddr
是监听地址,nameArg
是服务器名称。void setThreadNum(int numThreads)
:设置服务器的工作线程数。默认为 1,即单线程模式。void start()
:启动服务器,开始监听端口。void setConnectionCallback(const ConnectionCallback& cb)
:设置连接回调函数,当有新连接或连接断开时调用。void setMessageCallback(const MessageCallback& cb)
:设置消息回调函数,当有数据到达时调用。void setWriteCompleteCallback(const WriteCompleteCallback& cb)
:设置写完成回调函数,当所有数据写入完成后调用。
Kotlin
void setConnectionCallback(ConnectionCallback cb); // 连接建立/关闭回调
void setMessageCallback(MessageCallback cb); // 消息到达回调
示例代码:
Kotlin
#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>
#include <iostream>
void onConnection(const muduo::net::TcpConnectionPtr& conn) {
if (conn->connected()) {
std::cout << "New connection: " << conn->name() << std::endl;
} else {
std::cout << "Connection closed: " << conn->name() << std::endl;
}
}
void onMessage(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buf, muduo::Timestamp receiveTime) {
std::string msg(buf->retrieveAllAsString());
std::cout << "Received message: " << msg << std::endl;
conn->send(msg); // 回显消息
}
int main() {
muduo::net::EventLoop loop;
muduo::net::InetAddress listenAddr(8080);
muduo::net::TcpServer server(&loop, listenAddr, "EchoServer");
server.setConnectionCallback(onConnection);
server.setMessageCallback(onMessage);
server.setThreadNum(4); // 使用 4 个工作线程
server.start();
loop.loop();
return 0;
}
2.2EventLoop 类基础介绍
EventLoop
是 Muduo 库的核心类之一,负责事件循环(event loop)。每个线程只能有一个 EventLoop
实例,它负责监听和分发事件(如 I/O 事件、定时器事件等)。
常用接口:
void loop()
:启动事件循环,进入事件监听状态。void quit()
:退出事件循环。void runInLoop(const Functor& cb)
:在当前EventLoop
线程中执行回调函数cb
。如果调用者不在该线程中,则将回调函数加入队列,稍后执行。void queueInLoop(const Functor& cb)
:将回调函数cb
加入队列,稍后在EventLoop
线程中执行。TimerId runAt(const Timestamp& time, const TimerCallback& cb)
:在指定的时间点time
执行回调函数cb
。TimerId runAfter(double delay, const TimerCallback& cb)
:在指定的延迟时间delay
后执行回调函数cb
。TimerId runEvery(double interval, const TimerCallback& cb)
:每隔interval
秒执行一次回调函数cb
。
成员:
Kotlin
std::unique_ptr<Poller> poller_; // 底层 IO 多路复用(epoll/poll)
std::vector<Functor> pendingFunctors_; // 跨线程任务队列
核心方法
Kotlin
void loop(); // 启动事件循环(必须在本线程调用)
void quit(); // 停止循环
void runInLoop(Functor cb); // 跨线程安全的任务提交
TimerId runAfter(double delay, TimerCallback cb); // 定时器
代码示例:
Kotlin
#include <muduo/net/EventLoop.h>
#include <iostream>
void print() {
std::cout << "Hello, EventLoop!" << std::endl;
}
int main() {
muduo::net::EventLoop loop;
loop.runAfter(1.0, print); // 1秒后执行 print 函数
loop.loop(); // 启动事件循环
return 0;
}
2.3TcpConnection 基础介绍
TcpConnection
表示一个 TCP 连接。它是 TcpServer
的内部类,用于管理客户端与服务器之间的连接。每个连接都有一个唯一的 TcpConnection
对象。
void send(const void* data, int len)
:发送数据到客户端。void send(const StringPiece& message)
:发送字符串数据到客户端。void shutdown()
:关闭连接(半关闭,停止发送数据,但仍然可以接收数据)。void forceClose()
:强制关闭连接。bool connected() const
:判断连接是否处于连接状态。std::string name() const
:返回连接的名称(唯一标识符)。EventLoop* getLoop() const
:返回该连接所属的EventLoop
。
特性:
- 继承
std::enable_shared_from_this
,依赖智能指针管理生命周期。 - 通过
Channel
类注册到所属EventLoop
的Poller
。
Kotlin
void send(const void* data, size_t len); // 线程安全的发送接口
void shutdown(); // 半关闭连接(写端)
bool connected(); // 判断当前连接是否正常
示例代码:
Kotlin
void onMessage(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buf, muduo::Timestamp receiveTime) {
std::string msg(buf->retrieveAllAsString());
std::cout << "Received message: " << msg << std::endl;
if (msg == "quit\n") {
conn->shutdown(); // 如果收到 "quit",关闭连接
} else {
conn->send(msg); // 回显消息
}
}
2.4TcpClient 类基础介绍
TcpClient
用于创建 TCP 客户端。它可以连接到远程服务器并与之通信。
常用接口
TcpClient(EventLoop* loop, const InetAddress& serverAddr, const string& nameArg)
:构造函数,loop
是事件循环对象,serverAddr
是服务器地址,nameArg
是客户端名称。void connect()
:发起连接请求。void disconnect()
:断开连接。void setConnectionCallback(const ConnectionCallback& cb)
:设置连接回调函数。void setMessageCallback(const MessageCallback& cb)
:设置消息回调函数。
同步控制:
- 使用
CountDownLatch
等待连接建立完成后再发送数据:
Kotlin
CountDownLatch latch(1);
client.setConnectionCallback([&](const TcpConnectionPtr& conn) {
if (conn->connected()) latch.countDown();
});
client.connect();
latch.wait(); // 等待连接成功
示例代码:
Kotlin
#include <muduo/net/TcpClient.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>
#include <iostream>
void onConnection(const muduo::net::TcpConnectionPtr& conn) {
if (conn->connected()) {
std::cout << "Connected to server." << std::endl;
conn->send("Hello, server!\n");
} else {
std::cout << "Disconnected from server." << std::endl;
}
}
void onMessage(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buf, muduo::Timestamp receiveTime) {
std::string msg(buf->retrieveAllAsString());
std::cout << "Received from server: " << msg << std::endl;
}
int main() {
muduo::net::EventLoop loop;
muduo::net::InetAddress serverAddr("127.0.0.1", 8080);
muduo::net::TcpClient client(&loop, serverAddr, "EchoClient");
client.setConnectionCallback(onConnection);
client.setMessageCallback(onMessage);
client.connect();
loop.loop();
return 0;
}
2.5.Buffer 类基础介绍
Buffer
是 Muduo 中用于处理网络数据缓冲区的类。它实现了动态缓冲区的功能,支持高效的读写操作。
常用接口
void append(const char* data, size_t len)
:向缓冲区追加数据。size_t readableBytes() const
:返回可读字节数。size_t writableBytes() const
:返回可写字节数。const char* peek() const
:返回缓冲区中可读数据的起始位置。void retrieve(size_t len)
:从缓冲区中移除已读取的数据。std::string retrieveAllAsString()
:将缓冲区中的所有数据取出并转换为字符串。void prepend(const void* data, size_t len)
:在缓冲区前面插入数据。
示例代码:
Kotlin
void onMessage(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buf, muduo::Timestamp receiveTime) {
while (buf->readableBytes() >= sizeof(int)) {
const char* data = buf->peek();
int be32 = *reinterpret_cast<const int*>(data);
int host32 = muduo::net::sockets::networkToHost32(be32); // 转换为本地字节序
buf->retrieve(sizeof(int));
std::cout << "Received integer: " << host32 << std::endl;
}
}
3.总结
EventLoop
:负责事件循环,监听 I/O 事件和定时器事件。TcpServer
:用于创建 TCP 服务器,监听客户端连接。TcpConnection
:表示一个 TCP 连接,负责管理客户端与服务器之间的通信。TcpClient
:用于创建 TCP 客户端,连接到远程服务器。Buffer
:用于处理网络数据缓冲区,支持高效的读写操作。
这些类是 Muduo 库的核心组件,通过它们可以轻松构建高性能的 TCP 网络应用