利用Muduo库实现简单且健壮的Echo服务器

一、muduo网络库主要提供了两个类:

TcpServer:用于编写服务器程序

TcpClient:用于编写客户端程序

二、三个重要的链接库:

libmuduo_net、libmuduo_base、libpthread

三、muduo库底层就是epoll+线程池,其好处是:

可以将网络I/O代码和业务代码区分开,用户只需关注业务,网络的连接断开、读写事件的上报与监控交给muduo库

四、muduo库对外暴露两个业务接口:

1.用户的连接与断开

2.用户的可读写事件

五、基于muduo网络库的服务器开发步骤

1.组合TcpServer对象

2.创建Eventloop事件循环对象的指针

3.明确Tcpserver构造函数需要什么参数,输出Chatserver的构造函数

a.Tcpserver 主要提供两个回调函数:setConnectionCallback与setMessageCallback

b.在构造函数中定义回调函数,在类中定义具体回调的函数的实现

4.在当前服务类的构造函数中,注册处理连接的回调函数和处理读写事件的回调函数

5.设置合适的服务端线程数量,muduo库会自己分配I/O线程和work线程

cpp 复制代码
/*
muduo网络库主要提供了两个类:

TcpServer:用于编写服务器程序
TcpClient:用于编写客户端程序

三个重要的链接库:
libmuduo_net、libmuduo_base、libpthread

muduo库底层就是epoll+线程池,其好处是:
可以将网络I/O代码和业务代码区分开,用户只需关注业务,网络的连接断开、读写事件的上报与监控交给muduo库

只暴露两个业务接口:
1.用户的连接与断开
2.用户的可读写事件

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

/*
基于muduo网络库的服务器开发
1.组合TcpServer对象
2.创建Eventloop事件循环对象的指针
3.明确Tcpserver构造函数需要什么参数,输出Chatserver的构造函数
    a.Tcpserver 主要提供两个回调函数:setConnectionCallback与setMessageCallback
    b.在构造函数中定义回调函数,在类中定义具体回调的函数的实现
4.在当前服务类的构造函数中,注册处理连接的回调函数和处理读写事件的回调函数
5.设置合适的服务端线程数量,muduo库会自己分配I/O线程和work线程

*/
class ChatServer{
public:
    //构造函数对TcpServer进行初始化,TcpServer没有默认构造
    ChatServer(EventLoop *loop,//事件循环 reactor
               const InetAddress &listenAddr,//ip + port
               const string &nameArg)// 线程/server的名称
        : _server(loop, listenAddr, nameArg), _loop(loop)
    {
        //给服务器注册用户连接与断开的回调函数,当监听到连接/断开时执行onConnection,具体如何监听到是网络库的事情,无需用户操心
        _server.setConnectionCallback(std::bind(&ChatServer::onConnection,this,_1));//相当于this.onConnection(TcpConnectionPtr&)
        //给服务器注册用户读写事件的回调函数
        _server.setMessageCallback(std::bind(&ChatServer::onMessage,this,_1,_2,_3));
        //设置服务器端的线程数量,muduo库会自适应处理连接线程和工作线程的分配;CPU核数一般等于线程数
        //1个I/O线程,3个work线程
        _server.setThreadNum(4);
    }
    
    //开启事件循环
    void start(){
        _server.start();
    }

private:

    //专门处理用户的连接创建和断开,相当于epoll中监听到listenfd后执行accept
    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();//close(fd)
        }
    }
    //专门处理用户的读写事件
    void onMessage(const TcpConnectionPtr &conn,//连接的共享指针
                   Buffer *buffer,//缓冲区,存放数据
                   Timestamp time)//接收到数据的时间信息
    {
        //echo服务器
        string buf=buffer->retrieveAllAsString();
        cout<<"recv: "<<buf<<"time: "<<time.toString()<<endl;
        conn->send(buf);

    }
    TcpServer _server;// #1
    EventLoop *_loop;// #2 看作epoll

};

int main(){

    EventLoop loop;//类似于创建epoll
    InetAddress addr("127.0.0.1",6000);//本地回环地址,服务器仅接受来自本机的连接。适合在开发阶段进行本地调试。
    ChatServer server(&loop,addr,"ChatServer");
    server.start();//epoll_ctl,listenfd加入epoll
    loop.loop();//类似于epoll_wait,以阻塞的方式等待新用户连接,已连接用户的读写事件等
    return 0;
}

结果展示:

相关推荐
天诰4 小时前
SA-K-11 检索会消失吗与四个未解问题
java·服务器·人工智能·python·机器学习·ai编程
陈希1235 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡6 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
@兽血沸腾7 小时前
Windows系统安装Jenkins部署应用至远程Windows服务器操作指南
运维·服务器·jenkins
承渊政道10 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
讯捷蓝达12 小时前
戴尔R720xd服务器卡死在 “Configuring Memory...Done“,换了内存还是卡?问题根本不在内存
运维·服务器
数字新视界14 小时前
动环监控信创适配在智能机房管理中的应用价值与未来展望
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
爱和冰阔落14 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
lisanmengmeng15 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器
严肃小白兔15 小时前
Cloudflare 更新 API Token 管理:从最小权限到自动化凭据安全
网络·安全·自动化