muduo网络库使用入门

39 篇文章 1 订阅
13 篇文章 1 订阅

muduo网络库介绍

muduo网络库是陈硕大神开发的基于主从Reactor模式的,事件驱动的高性能网络库。

网络编程中有很多是事务性的工作,使用muduo网络库,用户只需要填上关键的业务逻辑代码,并将回调注册到框架中,就可以实现完整的网络服务。

muduo网络库的核心是one loop per thread + thread pool,有一个main Reactor负责accept连接,然后将连接挂在某个sub Reactor中(muduo通过round-robin算法选择一个sub Reactor)。这样该连接的所有操作都由该sub Reactor进行处理,多个连接可能被分派到多个线程中,以充分利用CPU。

muduo采用的是固定大小的Reactor poll,池的大小由用户进行设置,通常所有Reactor的个数应该等于CPU的数目。这样程序的总体处理能力不会随连接数增加而下降。由于一个连接完全由一个线程管理,那么请求的顺序性有保证,突发请求也不会占满所有CPU。把IO分配个多给线程,防止出现一个Reactor的处理能力饱和。

小规模计算可以在当前IO线程完成并发回结果,从而降低响应的延迟。如果需要大规模计算,可以再交给一个线程池让其进行处理,从而防止阻塞当前sub Reactor导致响应变慢。

如果TCP连接有优先级之分,可以将高优先级的连接放在一个单独的sub Reactor来处理,从而避免优先级反转。

muduo网络库环境搭建

参考博客:C++ muduo网络库知识分享01 - Linux平台下muduo网络库源码编译安装

使用muduo实现echo服务器

由于网络库封装了网络IO代码,所以不同的服务器的区别主要在于业务逻辑代码的不同。echo服务器简单地将来自客户端的数据回发给客户端,应该是业务逻辑最简单的服务器了,通过了解如何使用muduo网络库实现echo服务器有助于我们了解使用muduo网络库的基本方法,如果需要对网络部分进行优化就需要深入源码了解muduo网络库的实现原理,本文不详细涉及这部分(以后可能会更新关于muduo源码剖析的博客)。

使用muduo网络库我们需要组合TcpServer类,一般还需要保存EventLoop指针。EventLoop负责管理事件循环(epoll),TcpServer负责管理主Reactor(Acceptor管理连接socket)和从Reactors(EventLoopThreadPool管理客户端socket)以及对于每种事件的回调,这些回调会被合适的地方调用(对应事件发生的时候)。我们需要给TcpServer传入base loop、监听端口(和IP地址,一般是0.0.0.0)、服务器名称(打印日志),并且设置各种事件的回调,也就是在这里我们填入业务逻辑。


头文件EchoServer.h

// Copyright(C), Edward-Elric233
// Author: Edward-Elric233
// Version: 1.0
// Date: 2022/7/11
// Description: 
#ifndef CHATSERVER_ECHOSERVER_H
#define CHATSERVER_ECHOSERVER_H

#include "muduo/net/TcpServer.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/InetAddress.h"
#include "muduo/net/TcpConnection.h"
#include <string>

namespace edward {

    class EchoServer {
        using TcpServer = muduo::net::TcpServer;
        using EventLoop = muduo::net::EventLoop;
        using InetAddress = muduo::net::InetAddress;
        using TcpConnectionPtr = muduo::net::TcpConnectionPtr;
        using Buffer = muduo::net::Buffer;
        using Timestamp = muduo::Timestamp;
        TcpServer tcpServer_;
        EventLoop *loop_;
        void onConnectionCallback(const TcpConnectionPtr& conn);
        void onMessageCallback(const TcpConnectionPtr& conn, Buffer* buffer, Timestamp timestamp);
    public:
        EchoServer(EventLoop *loop, const InetAddress& address, const std::string &name);
        void start();
    };

}

#endif //CHATSERVER_ECHOSERVER_H

实现文件EchoServer.cpp

// Copyright(C), Edward-Elric233
// Author: Edward-Elric233
// Version: 1.0
// Date: 2022/7/11
// Description: 
#include "EchoServer.h"
#include "utils.h"
#include <functional>

namespace edward {
    using namespace std::placeholders;

    EchoServer::EchoServer(EventLoop *loop, const InetAddress& address, const std::string &name)
    : tcpServer_(loop, address, name)
    , loop_(loop) {
				//使用绑定器设置回调
        tcpServer_.setConnectionCallback(std::bind(&EchoServer::onConnectionCallback, this, _1));
        tcpServer_.setMessageCallback(std::bind(&EchoServer::onMessageCallback, this, _1, _2, _3));
				//根据本机的核数设置线程/Reactor数量,如果不设置默认为1个
        tcpServer_.setThreadNum(std::thread::hardware_concurrency());    
}

		//有新连接时的回调
    void EchoServer::onConnectionCallback(const TcpConnectionPtr& conn) {
        if (conn->connected()) {

        } else {

        }
    }

		//连接上有消息到来时的回调
    void EchoServer::onMessageCallback(const TcpConnectionPtr& conn, Buffer* buffer, Timestamp timestamp) {
        std::string msg = buffer->retrieveAllAsString();
        print(conn->peerAddress().toIpPort(), ":[", msg, "]at", timestamp.toFormattedString());
        conn->send(msg);
    }

    void EchoServer::start() {
        tcpServer_.start();  //使用epoll_ctl将连接socket放在loop上进行监听并设置对应的回调
    }

}

我们将回调都设置为成员函数,这样做的好处是我们往往要在回调中访问其他系统资源,成员函数可以访问数据成员避免传参。

测试文件test.cpp

#include "EchoServer.h"
void test_EchoServer() {
    muduo::net::EventLoop loop;
    edward::EchoServer echoServer(&loop, muduo::net::InetAddress(6789), "EchoServer");
    echoServer.start();
    loop.loop();
    return;
}

测试结果

20220711 09:47:44.055888Z 26057 INFO TcpServer::newConnection [EchoServer] - new connection [EchoServer-0.0.0.0:6789#1] from 127.0.0.1:41678 - TcpServer.cc:80
127.0.0.1:41678 :[ Hello world
]at 20220711 09:47:49.515927
127.0.0.1:41678 :[ 123456
]at 20220711 09:47:56.117636
20220711 09:47:57.069940Z 26057 INFO TcpServer::removeConnectionInLoop [EchoServer] - connection EchoServer-0.0.0.0:6789#1 - TcpServer.cc:109

结语

掌握了muduo网络基本的用法后就可以根据需要填充业务逻辑了,如果想要了解更多就需要深入源码去了解啦。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值