对别人写的mini-muduo的学习

本文详细分析了一位博主模仿muduo编写的mini-muduo库,重点讲解了多线程模型下的Echo服务器实现,涉及Epoll、Acceptor、Channel、线程池等关键组件的工作原理。通过对EchoServer、TcpServer、ThreadPool的逐层剖析,展示了从连接建立到消息收发的完整过程,揭示了异步I/O和多线程在网络编程中的应用。
摘要由CSDN通过智能技术生成

之前想学muduo 但因为一些原因,暂时编译不过,碰巧看到一个博主是模仿着muduo写的mini-muduo,看了看觉得挺好,仅仅实现Echo服务器,从最简单的epoll模型开始到反应堆+多线程,为了简洁没有使用智能指针(它也提示了会内存泄漏),部分有bug,但依旧是一个很好的学习对象。本文就最后的 反应堆+多线程模型作一下分析。(原文分成了13小节)

main.cpp

#include "TcpServer.h"
#include "EventLoop.h"
#include "EchoServer.h"

int main(int args, char** argv)
{
   
    EventLoop loop;
    EchoServer echoserver(&loop);
    echoserver.start();
    loop.loop();
    return 0;
}

接口都是一样的,一个服务器,一个loop,分别使用start loop方法就可以让程序跑起来,

EchoServer.h

#ifndef ECHOSERVER_H
#define ECHOSERVER_H

#include "IMuduoUser.h"
#include "IRun.h"
#include "TcpServer.h"
#include "ThreadPool.h"

class EchoServer : public IMuduoUser
                   , public IRun2
{
   
public:
    EchoServer(EventLoop* pLoop);
    ~EchoServer();
    void start();
    virtual void onConnection(TcpConnection* pCon);
    virtual void onMessage(TcpConnection* pCon, Buffer* pBuf);
    virtual void onWriteComplate(TcpConnection* pCon);

    virtual void run2(const string& str, void* tcp);
private:
    int fib(int n);
    EventLoop* _pLoop;
    TcpServer _pServer;
    ThreadPool _threadpool;
    long _timer;
    int _index;
};

#endif

这个EchoServer 是应用层面的服务器,继承于IMuduoUser和IRun2。IMuduoUser类包含onConnection,onMessage,onWriteComplate三个虚函数,要求子类EchoServer实现,分别对应着连接时,收到消息时,发送消息完成时需要的部分处理,
IRun2类虚函数是run2,这个函数运用于回调。
EventLoop* _pLoop是事件轮讯对象指针,TcpServer _pServer是服务器对象,ThreadPool _threadpool是线程池,_timer是计时器的地址(原博主的意思是用计时器的id,但他直接使用了计时器的指针存放在long类型的_timer里,可以说是有点古怪,后面需要多次的转型)
_index暂无使用

EchoServer.cc

#include "EchoServer.h"
#include "TcpConnection.h"
#include "EventLoop.h"
#include "CurrentThread.h"
#include "Task.h"

#include <iostream>

#define MESSAGE_LENGTH 8

EchoServer::EchoServer(EventLoop* pLoop)
    :_pLoop(pLoop)
    ,_pServer(pLoop)
    ,_timer(-1)
    ,_index(0)
{
   
    _pServer.setCallback(this);
}

EchoServer::~EchoServer()
{
   }

void EchoServer::start()
{
   
    _pServer.start();
    _threadpool.start(3);
}

void EchoServer::onConnection(TcpConnection* pCon)
{
   
    printf("%s\n",__func__);

    cout << "onConnection" << endl;
}

void EchoServer::onMessage(TcpConnection* pCon, Buffer* pBuf)
{
   
    printf("%s\n",__func__);

    while(pBuf->readableBytes() > MESSAGE_LENGTH)
    {
   
        string message = pBuf->retrieveAsString(MESSAGE_LENGTH);
        Task task(this, message, pCon);
        _threadpool.addTask(task);
    }
    if (pBuf->readableBytes() <= MESSAGE_LENGTH){
   
        string message = pBuf->retrieveAllAsString();
        Task task(this, message, pCon);
        _threadpool.addTask(task);
    }
}

void EchoServer::onWriteComplate(TcpConnection* pCon)
{
   
    printf("%s\n",__func__);

    cout << "onWriteComplate" << endl;
}

//run in different therad
void EchoServer::run2(const string& str, void* tcp)
{
   
    printf("%s\n",__func__);

    //IO blocking task or CPU busy task
    cout << "fib(30) = " << fib(30) << " tid = " << CurrentThread::tid() << endl;
    ((TcpConnection*)tcp)->send(str);
}

//fib is short for Fibonacci, fib is a CPU busy method
int EchoServer::fib(int n)
{
   
    return (n == 1 || n == 2) ? 1 : (fib(n-1) + fib(n-2));
}

可以看到 onConnection,onWriteComplate类仅仅是打印一下函数名称, printf("%s\n",__func__);是我为了打印函数执行流程而打印的,使用时可去除。
先不看run2 ,fib,onMessage,而是看main里面的echoserver.start

void EchoServer::start()
{
   
    _pServer.start();
    _threadpool.start(3);
}

转到TcpServer

TcpServer.h

//author voidccc
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <sys/epoll.h>

#include "Declear.h"
#include "Define.h"
#include "IAcceptorCallback.h"
#include "IMuduoUser.h"

#include <map>
using namespace std;

class TcpServer : public IAcceptorCallback
{
   
    public:
        TcpServer(EventLoop* pLoop);
        ~TcpServer();
        void start();
        void setCallback(IMuduoUser* pUser);
        virtual void newConnection(int sockfd);
    private:
        struct epoll_event _events[MAX_EVENTS];
        map<int, TcpConnection*> _connections;
        Acceptor* _pAcceptor;
        EventLoop* _pLoop;
        IMuduoUser* _pUser;
};

#endif

TcpServer.cc

//author voidccc

#include <errno.h>

#include "TcpServer.h"
#include "Channel.h"
#include "Acceptor.h"
#include "TcpConnection.h"

#include <vector>

TcpServer::TcpServer(EventLoop* pLoop)
    :_pAcceptor(NULL)
    ,_pLoop(pLoop)
    ,_pUser(NULL)
{
   
}

TcpServer::~TcpServer()
{
   
}

void TcpServer::start()
{
   
    _pAcceptor = new Acceptor(_pLoop); // Memory Leak !!!
    _pAcceptor->setCallback(this);
    _pAcceptor->start();
}

void TcpServer::newConnection(int sockfd)
{
   
    TcpConnection* tcp = new TcpConnection(sockfd, _pLoop); // Memory Leak !!!
    _connections[sockfd] = tcp;
    tcp->setUser(_pUser);
    tcp->connectEstablished();
}

void TcpServer::setCallback(IMuduoUser* user)
{
   
    _pUser = user;
}

直接看TcpServer.start里面new了一个Accpetor

Accpetor.h

//author voidccc
#ifndef ACCEPTOR_H
#define ACCEPTOR_H

#include "Declear.h"
#include "Define.h"
#include "IChannelCallback.h"

class Acceptor : public IChannelCallback
{
   
    public:
        Acceptor(EventLoop* pLoop);
        ~Acceptor();

        void start();
        void setCallback(IAcceptorCallback* pCallback);
        virtual void handleRead();
        virtual void handleWrite();
    private:
        int createAndListen();
        int _listenfd;
        Channel* _pSocketAChannel;
        IAcceptorCallback* _pCallback;
        EventLoop* _pLoop;
};

#endif

跳到Acceptor.cc内
直接看start,

Acceptor.cc


#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>

#include "Acceptor.h"
#include "Channel.h"
#include "IAcceptorCallback.h"
#include "EventLoop.h"

#include <iostream>
using namespace std;

Acceptor::Acceptor(EventLoop* pLoop)
    :_listenfd(-1)
    ,_pSocketAChannel(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值