C++Muduo网络库:简介及使用

一、Muduo网络库简介

Muduo网络库:底层实质上为Linux的epoll + pthread线程池,且依赖boost库。 muduo的网络设计核心为一个线程一个事件循环,有一个main Reactor负载accept连接,然后把连接分发到某个sub Reactor(采用轮询的方式来选择sub Reactor),该连接的所用操作都在那个sub Reactor所处的线程中完成。多个连接可能被分派到多个线程中,以充分利用CPU,Reactor poll的大小是固定的,根据CPU的数目确定。如果有过多的耗费CPU I/O的计算任务,可以提交到创建的ThreadPool线程池中专门处理耗时的计算任务。
关于Reactor模型详解可参考此篇博客:高性能网络服务器基础
      一般我们见到的高并发网络模型如下,有一个I/O线程(epoll),专门处理新用户链接;新用户链接完成后通过特定算法分发给不同的工作线程,线程数一般与CPU核数对等,工作线程专门处理已链接用户的读写事件。
在这里插入图片描述
 

二、服务器编程实例

muduo网络库实质为: epoll + 线程池,优点是能够将网络I/O的代码和业务代码分开。 而业务代码主要分为:用户的连接和断开、用户的可读写事件两类。至于什么时候发生这些事件,由网络库进行上报,如何监听这些事件,都是网络库所封装好的,我们就可以快速进行项目开发。

muduo给用户提供了两个主要的类:
1、TcpServer:用于编写服务器程序。
2、TcpClient:用于编写客户端程序。
 

2.1 环境配置

我们是vscode远程在Linux上进行开发的,需要提前安装好muduo网络库,搭建vscode远程开发环境,如下:
1、moduo库安装:Linux平台下muduo网络库源码编译安装
2、vscode远程环境配置:windows+vscode搭建远程linux开发环境

以上环境安装好后,因为我们使用的为第三方库,代码编译完成后需要链接相应的.so库,可以通过以下两种不同的方式进行链接:
在这里插入图片描述
1、我们可以在终端上通过命令方式手动进行链接相应库文件,如下:
在这里插入图片描述
2、按F1调出vscode编译配置文件c_cpp_properties.json,依据自己需要修改配置。
在这里插入图片描述
也可以按ctrl + shift + b,点击齿轮。
在这里插入图片描述
进入task.json依据自己需要配置链接库。
在这里插入图片描述
 

2.2 服务器编程

muduo库服务器编程流程:
1、组合TcpServer对象;
2、创建EventLoop事件循环对象的指针,可以向loop上注册感兴趣的事件,相应事件发生loop会上报给我们;
3、明确TcpServer构造函数需要的参数,输出服务器对应类的构造函数;

  TcpServer(EventLoop* loop, //事件循环
            const InetAddress& listenAddr, //绑定IP地址 + 端口号
            const string& nameArg, //TcpServer服务器名字
            Option option = kNoReusePort); //tcp协议选项

4、在当前服务器类的构造函数中,注册处理连接断开的回调函数和处理读写事件的回调函数主要通过下面两个函数回调实现;

 void setConnectionCallback(const ConnectionCallback& cb) //链接的创建与断开
 { connectionCallback_ = cb; }

 void setMessageCallback(const MessageCallback& cb) //消息读写事件
 { messageCallback_ = cb; }

5、设置合适的服务器端线程数量,muduo会自动分配I/O线程与工作线程;
6、开启事件循环start();

muduo服务器端编程代码如下:

#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
#include <iostream>
#include <functional>
#include <string>
using namespace std;
using namespace muduo;
using namespace muduo::net;
using namespace placeholders;

//基于muduo网络库开发服务器程序
class ChatServer
{
public:
    //3、明确TcpServer构造函数需要的参数,输出服务器对应类的构造函数
    ChatServer(EventLoop *loop, const InetAddress &listenAddr, const string &nameArg) //事件循环、IP+port、服务器名字
    : _server(loop, listenAddr, nameArg), _loop(loop)
    {
        //4.1、注册用户连接的创建和断开事件的回调
        _server.setConnectionCallback(std::bind(&ChatServer::onConnection, this, _1)); //利用绑定器绑定成员方法onConnection,保持参数与muduo库函数参数一致
        
        //4.2、注册用户读写事件的回调
        _server.setMessageCallback(std::bind(&ChatServer::onMessage, this, _1, _2, _3)); //利用绑定器绑定成员方法onMessage,保持参数与muduo库函数参数一致

        //5、设置服务器端的线程数量
        _server.setThreadNum(4);
    }

    //6.开启事件循环
    void start()
    {
        _server.start();
    }

private:
    //4.1 专门处理用户的连接和断开
    void onConnection(const TcpConnectionPtr &conn) //连接
    {
        if (conn->connected())
        {
            cout << conn->peerAddress().toIpPort() << " -> " << conn->localAddress().toIpPort() << "state:online" << endl;
        }
        else
        {
            cout << conn->peerAddress().toIpPort() << " -> " << conn->localAddress().toIpPort() << "state:offline" << endl;
            conn->shutdown(); //连接断开将socket资源释放
            //或者调用_loop->quit()退出epoll;
        }
    }

    //4.2 专门处理用户读写事件
    void onMessage(const TcpConnectionPtr &conn, Buffer *buffer, Timestamp time) //连接、缓冲区、接收到数据的事件信息
    {
        string buf = buffer->retrieveAllAsString(); //将接收数据全部放入字符串中
        cout << "recv data:" << buf << " time:" << time.toString() << endl;
        conn->send(buf); //收到什么数据发回去什么数据
    }

    TcpServer _server; //1、组合TcpServer对象
    EventLoop *_loop; //2、创建EventLoop事件循环对象的指针
};

int main()
{
    EventLoop loop; //epoll
    InetAddress addr("127.0.0.1", 6000);
    ChatServer server(&loop, addr, "ChatServer");

    server.start(); //启动服务:listenfd通过epoll_ctl添加到epoll上
    loop.loop(); //类似于epoll_wait以阻塞的方式等待新用户连接或处理已连接用户的读写事件

    return 0;
}

 

2.3 运行及测试

我们调用了muduo第三方库,因此代码编译完成后还需要链接相应库文件,muduo_net必须写在muduo_base前面(muduo_base依赖了muduo_net库),命令如下:
在这里插入图片描述
执行程序./server,我们新打开一个终端充当客户端,发送相应数据可以看到服务器可以正常回显。
在这里插入图片描述
此时我们客户端进行退出(telnet退出为ctrl + ]),连接断开,可以看到服务器也能够正常退出。
在这里插入图片描述

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux多线程服务端编程是指使用Muduo C网络Linux操作系统中进行多线程的服务端编程。Muduo C网络是一个基于事件驱动的网络,采用了Reactor模式,并且在底层使用了epoll来实现高效的I/O复用。 使用Muduo C网络进行多线程服务端编程有以下几个步骤: 1. 引入Muduo C网络:首先需要下载并引入Muduo C网络的源代码,然后在编写代码时包含相应的头文件。 2. 创建并初始化EventLoop:首先需要创建一个EventLoop对象,它用于接收和分发事件。通过初始化函数进行初始化,并在主线程中调用它的loop()函数来运行事件循环。 3. 创建TcpServer:然后创建一个TcpServer对象,它负责监听客户端的连接,并管理多个TcpConnection对象。通过设置回调函数,可以在特定事件发生时处理相应的逻辑。 4. 创建多个EventLoopThread:为了提高并发性能,可以创建多个EventLoopThread对象,每个对象负责一个EventLoop,从而实现多线程处理客户端的连接和请求。 5. 处理事件:在回调函数中处理特定事件,例如有新的连接到来时会调用onConnection()函数,可以在该函数中进行一些初始化操作。当有数据到来时会调用onMessage()函数,可以在该函数中处理接收和发送数据的逻辑。 6. 运行服务端:在主线程中调用TcpServer的start()函数来运行服务端,等待客户端的连接和请求。 总的来说,使用Muduo C网络进行Linux多线程服务端编程可以更好地利用多核处理器的性能优势。每个线程负责处理特定事件,通过事件驱动模式实现高效的网络编程。这样可以提高服务器的并发能力,提高系统的整体性能。 ### 回答2: Linux多线程服务端编程是指在Linux平台上使用多线程的方式来编写网络服务器程序。而使用muduo C网络是一种常见的方法,它提供了高效的网络编程接口,可以简化多线程服务器的开发过程。 muduo C网络基于Reactor模式,利用多线程实现了高并发的网络通信。在使用muduo C进行多线程服务端编程时,我们可以按照以下步骤进行: 1. 引入muduo:首先需要导入muduo C网络的头文件,并链接对应的文件,以供程序调用。 2. 创建线程池:利用muduo C中的ThreadPool类创建一个线程池,用于管理和调度处理网络请求的多个线程。 3. 创建TcpServer对象:使用muduo C中的TcpServer类创建一个服务器对象,监听指定的端口,并设置好Acceptor、TcpConnectionCallback等相关回调函数。 4. 定义业务逻辑:根据具体的业务需求,编写处理网络请求的业务逻辑代码,如接收客户端的请求、处理请求、发送响应等。 5. 注册业务逻辑函数:将定义好的业务逻辑函数注册到TcpServer对象中,以便在处理网络请求时调用。 6. 启动服务器:调用TcpServer对象的start函数,启动服务器,开始监听端口并接收客户端请求。 7. 处理网络请求:当有客户端连接到服务器时,muduo C会自动分配一个线程去处理该连接,执行注册的业务逻辑函数来处理网络请求。 8. 释放资源:在程序结束时,需要调用相应的函数来释放使用的资源,如关闭服务器、销毁线程池等。 通过使用muduo C网络,我们可以简化多线程服务端编程的过程,提高服务器的并发处理能力。因为muduo C网络已经实现了底层的网络通信细节,我们只需要专注于编写业务逻辑代码,从而减少开发的工作量。同时,muduo C的多线程模型可以有效地提高服务器的并发性能,满足高并发网络服务的需求。 ### 回答3: Linux多线程服务端编程是指在Linux操作系统上开发多线程的服务器应用程序。使用muduo C网络有助于简化开发过程,提供高效的网络通信能力。 muduo C网络是一个基于Reactor模式的网络,适用于C++语言,由Douglas Schmidt的ACE网络演化而来。它提供了高度并发的网络编程能力,封装了许多底层细节,使得开发者能够更加专注于业务逻辑的实现。 在开发过程中,首先需要创建一个muduo C的EventLoop对象来管理事件循环。然后,可以利用TcpServer类来创建服务器并监听指定的端口。当有新的客户端请求到达时,muduo C会自动调用用户定义的回调函数处理请求。 在处理请求时,可以使用muduo C提供的ThreadPool来创建多个工作线程。这些工作线程将负责处理具体的业务逻辑。通过将工作任务分配给不同的线程,可以充分利用多核服务器的计算资源,提高服务器的处理能力。 在具体的业务逻辑中,可以使用muduo C提供的Buffer类来处理网络数据。Buffer类提供了高效的数据读写操作,可以方便地进行数据解析与封装。 此外,muduo C还提供了TimerQueue类来处理定时任务,可以用于实现定时事件的调度与管理。这对于一些需要定期执行的任务非常有用,如心跳检测、定时备份等。 总之,使用muduo C网络可以简化Linux多线程服务端编程的开发过程,提供高效的并发能力。通过合理地利用多线程和其他的相关组件,可以实现高性能、稳定可靠的网络服务端应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值