集群聊天室项目--muduo网络库的搭建及测试

Muduo 网络库完整搭建教程(Linux 环境)

Muduo 是基于 Reactor 模式的 Linux 专属 C++ 网络库,搭建核心是安装依赖→编译源码→验证安装,以下是 Ubuntu/CentOS 通用步骤,包含环境配置、编译细节、验证测试和常见问题解决。

一、搭建前提

  • 操作系统:Linux(推荐 Ubuntu 18.04+/CentOS 7+,muduo 依赖 epoll,不支持 Windows/macOS);
  • 核心依赖:C++ 编译器(gcc 4.8+)、CMake(3.0+)、Boost 库(1.58+)、Git(拉取源码)。

二、分步搭建流程

步骤 1:安装基础编译工具与依赖

复制代码
# 更新软件源
sudo apt update

# 安装基础编译工具(gcc/g++/make/cmake)
sudo apt install -y build-essential cmake

# 安装 Boost 库(muduo 依赖 boost-thread/boost-system)
sudo apt install -y libboost-dev libboost-thread-dev

# 安装 Git(拉取源码)
sudo apt install -y git

步骤 2:拉取 Muduo 源码

复制代码
# 克隆官方仓库(若网络慢,可换国内镜像,如 gitee 镜像)
git clone https://github.com/chenshuo/muduo.git

# 进入源码目录
cd muduo

步骤 3:编译 Muduo 源码

Muduo 采用 CMake 构建,编译前需创建构建目录,避免污染源码:

复制代码
# 创建 build 目录(规范编译目录)
mkdir build && cd build

# 配置 CMake(指定安装路径为 /usr/local,方便系统查找)
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local

# 编译(-j 后接线程数,建议等于 CPU 核心数,加速编译)
# 例如 4 线程:make -j4
make -j$(nproc)

步骤 4:安装 Muduo 库(关键)

编译完成后,将库文件和头文件安装到系统目录(/usr/local),方便后续项目链接:

复制代码
sudo make install

步骤 5:验证安装是否成功

安装后会生成两类文件,检查是否存在即可确认:

复制代码
# 检查头文件(muduo 核心头文件)
ls /usr/local/include/muduo/

# 检查库文件(静态库,muduo_base 基础库 + muduo_net 网络库)
ls /usr/local/lib/libmuduo_*.a

正常输出应包含:

  • 头文件:muduo/base/muduo/net/ 等目录;
  • 库文件:libmuduo_base.alibmuduo_net.a

三、测试搭建结果(编写简单程序验证)

服务器代码:

cpp 复制代码
#include<muduo/net/TcpServer.h>
#include<muduo/net/EventLoop.h>
#include<functional>
#include<string>
#include<iostream>
using namespace muduo;
using namespace muduo::net;
using namespace std;
class ChatServer
{
    TcpServer server_;
    EventLoop* loop_;
    //上报连接相关信息的回调函数
    void onConnection(const TcpConnectionPtr&);
    //上报读写事件相关信息的回调函数
    void onMessage(const TcpConnectionPtr&,Buffer*,Timestamp);
public:
    ChatServer(EventLoop*loop, const InetAddress& listenAddr,const string& nameArg);
    void start();

};
void ChatServer::onConnection(const TcpConnectionPtr &conn)
{
    if (conn->connected())
    {
        printf("ChatServer - %s connected\n", conn->peerAddress().toIpPort().c_str());
    }
    else
    {
        printf("ChatServer - %s disconnected\n", conn->peerAddress().toIpPort().c_str());
        conn->shutdown();
    }
}

void ChatServer::onMessage(const TcpConnectionPtr &conn, Buffer *buffer, Timestamp time)
{
    string buff=buffer->retrieveAllAsString();
    printf("ChatServer received message:%s\n", buff.c_str());
    conn->send(buff);
}

ChatServer::ChatServer(EventLoop *loop, const InetAddress &listenAddr, const string &nameArg) : loop_(loop), server_(loop, listenAddr, nameArg)
{
    server_.setConnectionCallback(
        std::bind(&ChatServer::onConnection,this,_1)
    );
    server_.setMessageCallback(
        std::bind(&ChatServer::onMessage,this,_1,_2,_3)
    );

    server_.setThreadNum(4);
}

void ChatServer::start()
{
    server_.start();
}

int main(){
    EventLoop loop;
    InetAddress addr("127.0.0.1", 6000);
    ChatServer server(&loop, addr, "ChatServer");
    server.start();
    loop.loop();
    return 0;
}

代码讲解:

代码分为 3 个核心部分:

  1. 头文件与命名空间:引入 Muduo 核心组件 + 基础工具;

  2. ChatServer 类封装:将服务器逻辑封装为类,包含连接 / 消息回调、服务器对象、Reactor 核心等;

  3. main 函数:初始化 Reactor 循环、监听地址、启动服务器,是程序入口。

1. 头文件与命名空间(基础依赖)
cpp 复制代码
#include<muduo/net/TcpServer.h>   // Muduo 服务器核心类,封装监听/连接管理/线程池
#include<muduo/net/EventLoop.h>   // Reactor 核心,负责 epoll 事件循环
#include<functional>              // 用于 std::bind 绑定类成员函数为回调
#include<string>
#include<iostream>
using namespace muduo;            // 简化 muduo 库命名
using namespace muduo::net;       // 简化 muduo 网络模块命名
using namespace std;              // 简化标准库命名
  • TcpServer:Muduo 封装的 TCP 服务器,无需手动处理 epoll/accept,只需注册回调即可;

  • EventLoop:Reactor 模式的核心,每个线程最多一个,负责事件监听、分发;

  • functional:因为类的成员函数有隐含的 this 指针,需用 std::bind 绑定后才能适配 Muduo 的回调类型。

2. ChatServer 类定义(核心封装)
cpp 复制代码
class ChatServer
{
    // 成员变量:
    TcpServer server_;    // Muduo 服务器对象(核心)
    EventLoop* loop_;     // Reactor 事件循环指针(指向主线程的 EventLoop)

    // 私有成员函数(回调函数):
    void onConnection(const TcpConnectionPtr&);  // 连接状态变化回调
    void onMessage(const TcpConnectionPtr&,Buffer*,Timestamp);  // 数据读写回调

public:
    // 构造函数:初始化服务器对象、绑定回调、设置线程池
    ChatServer(EventLoop*loop, const InetAddress& listenAddr,const string& nameArg);
    void start();  // 启动服务器
};
  • 成员变量设计

    • server_TcpServer 是服务器的核心载体,封装了监听、连接管理、线程调度;

    • loop_:指向主线程的 EventLoop,传递给 TcpServer 后,服务器的 Acceptor(监听模块)会运行在该 EventLoop 中。

  • 回调函数声明

    • onConnection:处理 "连接建立 / 断开" 事件;

    • onMessage:处理 "数据接收" 事件,参数包含连接对象、数据缓冲区、接收时间戳(Muduo 预定义的回调参数格式)。

3. onConnection 回调函数(连接事件处理)
cpp 复制代码
void ChatServer::onConnection(const TcpConnectionPtr &conn)
{
    if (conn->connected())  // 判断连接是否建立(三次握手完成)
    {
        printf("ChatServer - %s connected\n", conn->peerAddress().toIpPort().c_str());
    }
    else  // 连接断开(四次挥手/网络异常)
    {
        printf("ChatServer - %s disconnected\n", conn->peerAddress().toIpPort().c_str());
        conn->shutdown();  // 主动关闭连接(半关闭写端,释放资源)
    }
}
  • 核心参数 TcpConnectionPtr :是 std::shared_ptr<TcpConnection> 的别名,Muduo 用智能指针管理连接生命周期,避免野指针;

  • 关键接口

    • conn->connected():判断当前连接是否处于 "已建立" 状态;

    • conn->peerAddress():获取客户端的 IP:Port(InetAddress 类型),toIpPort() 转为字符串;

    • conn->shutdown():主动关闭连接(关闭写端,触发 TCP 四次挥手,避免资源泄漏)。

4. onMessage 回调函数(数据读写处理)
cpp 复制代码
void ChatServer::onMessage(const TcpConnectionPtr &conn, Buffer *buffer, Timestamp time)
{
    string buff=buffer->retrieveAllAsString();  // 读取缓冲区所有数据并清空
    printf("ChatServer received message:%s\n", buff.c_str());
    conn->send(buff);  // 回显数据给客户端(异步发送)
}
  • 参数解析

    • Buffer* buffer:Muduo 封装的缓冲区,解决 TCP 粘包 / 拆包问题(流式协议无消息边界);

    • Timestamp time:数据接收完成的时间戳(示例中未使用,可用于日志 / 性能统计);

  • 核心操作

    • buffer->retrieveAllAsString():读取缓冲区中所有可读数据,转为字符串,并移动读指针(清空缓冲区);

    • conn->send(buff):异步发送数据给客户端 ------ 若数据能一次性写入 socket,则直接发送;若写满,则存入写缓冲区,等待 EPOLLOUT 事件触发后继续发送(Muduo 自动处理,无需手动关注非阻塞写)。

5. ChatServer 构造函数(初始化核心逻辑)
cpp 复制代码
ChatServer::ChatServer(EventLoop *loop, const InetAddress &listenAddr, const string &nameArg) 
    : loop_(loop), server_(loop, listenAddr, nameArg)  // 初始化列表
{
    // 绑定连接回调:将类成员函数 onConnection 转为 Muduo 可识别的回调类型
    server_.setConnectionCallback(
        std::bind(&ChatServer::onConnection,this,_1)
    );
    // 绑定消息回调:将类成员函数 onMessage 转为 Muduo 可识别的回调类型
    server_.setMessageCallback(
        std::bind(&ChatServer::onMessage,this,_1,_2,_3)
    );

    server_.setThreadNum(4);  // 设置工作线程池大小为 4
}
  • 初始化列表注意点 :类中 server_ 声明在 loop_ 之前,但初始化列表先初始化 loop_、后初始化 server_------ 编译器会触发 "成员初始化顺序不匹配" 警告(不影响功能,但建议调整类成员声明顺序:先 loop_,后 server_)。

  • 回调绑定核心(std::bind) :Muduo 的回调类型是 std::function,而类的成员函数有隐含的 this 指针,需用 std::bind 绑定:

    • this:指向当前 ChatServer 对象,保证回调能调用到当前对象的成员函数;

    • _1/_2/_3:占位符,对应回调函数的参数(onConnection 有 1 个参数,onMessage 有 3 个参数)。

  • setThreadNum(4):设置 Muduo 的工作线程池大小为 4------Muduo 采用 "单 Reactor 多线程" 模型:

    • 主线程(Reactor 线程):处理 Acceptor 监听事件(新连接建立);

    • 4 个工作线程:处理已建立连接的读写事件(onMessage 运行在工作线程)。

6. start 成员函数(启动服务器)
cpp 复制代码
void ChatServer::start()
{
    server_.start();  // 调用 TcpServer::start(),底层启动 Acceptor 监听端口 + 启动工作线程池
}
  • TcpServer::start() 做两件核心事:
    1. 启动 Acceptor:调用 listen() 监听指定端口,开始接收新连接;
    2. 启动线程池:创建 4 个工作线程,每个线程绑定一个 EventLoop,用于处理连接的读写事件。
7. main 函数(程序入口)
cpp 复制代码
int main(){
    EventLoop loop;  // 创建主线程的 EventLoop(Reactor 核心,阻塞运行)
    InetAddress addr("127.0.0.1", 6000);  // 监听地址:127.0.0.1:6000
    ChatServer server(&loop, addr, "ChatServer");  // 创建服务器对象
    server.start();  // 启动服务器
    loop.loop();     // 启动 Reactor 事件循环(阻塞,直到退出)
    return 0;
}
  • 核心流程

    1. EventLoop loop:主线程创建 EventLoop,是整个服务器的 "心脏",负责 epoll 事件监听 / 分发;

    2. InetAddress addr:指定服务器监听的 IP 和端口(127.0.0.1 表示仅本地可访问,若需外网访问改为 0.0.0.0);

    3. ChatServer server:初始化服务器,绑定回调、设置线程池;

    4. server.start():启动监听和线程池;

    5. loop.loop():进入无限循环,调用 epoll_wait 等待事件(新连接、数据读写、信号等),并分发事件到对应回调 ------这行代码会阻塞主线程,直到服务器退出

运行结果:

相关推荐
cui_win1 小时前
HTTP协议:常见状态码(400/500 系列)
网络·网络协议·http
没有bug.的程序员1 小时前
GC日志解析:从日志看全流程
java·网络·jvm·spring·日志·gc
上海云盾安全满满1 小时前
入侵检测系统如何保障网络安全
网络·安全·web安全
渡我白衣2 小时前
并行的野心与现实——彻底拆解 C++ 标准并行算法(<execution>)的模型、陷阱与性能真相
java·开发语言·网络·c++·人工智能·windows·vscode
xu_yule2 小时前
网络和Linux网络-8(传输层)TCP协议(流量控制+滑动窗口+拥塞控制+紧急指针+listen第二个参数)
linux·网络·tcp/ip
闲人编程2 小时前
网络安全基础与常见攻击防护
网络·安全·web安全·攻击·codecapsule·攻击防护
北京耐用通信2 小时前
工业通信升级利器:耐达讯自动化Ethernet/IP转CC-Link网关让IO模块兼容无忧!
网络·人工智能·科技·物联网·网络协议·自动化·信息与通信
刘孬孬沉迷学习2 小时前
SCTP、GTP-U 和 WebSocket 协议比较
网络·websocket·网络协议
一水鉴天3 小时前
整体设计中的三个“闭”概念-闭集或度量空间:有序闭环Z、有界闭域R和有限闭群C
网络·人工智能·算法