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 类基础介绍
- 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) :设置写完成回调函数,当全部数据写入完成后调用。
- void setConnectionCallback(ConnectionCallback cb); // 连接建立/关闭回调
- void setMessageCallback(MessageCallback cb); // 消息到达回调
复制代码 示例代码:
- #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。
成员:
- std::unique_ptr<Poller> poller_; // 底层 IO 多路复用(epoll/poll)
- std::vector<Functor> pendingFunctors_; // 跨线程任务队列
复制代码 核心方法
- void loop(); // 启动事件循环(必须在本线程调用)
- void quit(); // 停止循环
- void runInLoop(Functor cb); // 跨线程安全的任务提交
- TimerId runAfter(double delay, TimerCallback cb); // 定时器
复制代码 代码示例:
- #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。
- void send(const void* data, size_t len); // 线程安全的发送接口
- void shutdown(); // 半关闭连接(写端)
- bool connected(); // 判断当前连接是否正常
复制代码 示例代码:
- 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 等待连接建立完成后再发送数据:
- CountDownLatch latch(1);
- client.setConnectionCallback([&](const TcpConnectionPtr& conn) {
- if (conn->connected()) latch.countDown();
- });
- client.connect();
- latch.wait(); // 等待连接成功
复制代码 示例代码:
- #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) :在缓冲区前面插入数据。
示例代码:
- 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 网络应用
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |