muduo echo服务器测试

echo 服务器测试

/*
    muduo网络库给用户提供了两个主要的类
    TCPServer:用于编写服务器程序
    TCPClient:用于编写客户端程序

    epoll+线程池
    好处:能够把网络I/O的代码和业务代码区分开,主要开发业务,网络库代码封装了
    业务代码暴漏:1。用户的连接和断开2.用户可读写事件
*/
#include<muduo/net/TcpServer.h>
#include<muduo/net/EventLoop.h>
#include<string>
#include<iostream>
#include<functional>
using namespace muduo;
using namespace muduo::net;
using namespace std;

//基于muduo网络库开发服务器程序
/*
    1.组合TcpServer对象
    2.创建EventLoop事件循环对象的指针
    3.明确TcpServer构造函数需要什么参数,输出ChatServer的构造函数
    4.在当前服务器类的构造函数中,注册处理链接的回调函数和处理读写事件的回调函数
    5.设置合适的服务端线程数量,muduo库会自己划分I/O和woker线程
*/
class ChatServer
{
public:
    ChatServer(EventLoop* loop, 
            const InetAddress& listenAddr,
            const string& nameArg)
            :_server(loop,listenAddr,nameArg)
            ,_loop(loop)
            {
                //将网络代码和业务代码区分开
                //普通函数 我知道这个函数就要在这里发生,也知道会发生什么(在什么地方发生,在发生之后怎么做)
                //给服务器注册用户连接创建和断开回调(回调 模块解耦的重点)
                //知道了该怎么做,但是不知道什么时候会发生,对端发送消息才知道用户连接的创建和断开,数据读写请求,网络库来监听,接听到对端发送的业务请求,注册回调,相应的事件发生后,帮我们调用相应的回调函数,在回调中开发业务

                //连接的创建和断开 setConnectionCallback 返回值<void (const TcpConnectionPtr&) 没有返回值,一个成员变量
                //消息的读写的事件 setMessageCallback 

                //成员方法自带this指针,使用绑定器处理问题,底层监听到就会帮我们调用
                _server.setConnectionCallback(std::bind(&ChatServer::onConnection,this,_1));
                //给服务器注册用户读写事件回调
                _server.setMessageCallback(std::bind(&ChatServer::onMessage,this,_1,_2,_3));
                //设置服务端的线程数量 1个I/O 3个工作线程
                _server.setThreadNum(4);
            }

            //开启事件循环
            void start()
            {
                _server.start();
            }
private:
    //专门处理用户的连接创建和断开 (自行在muduo库上注册了)
    //从epoll拿来事件 listenfd 从listenfd上accept表示有新用户连接 拿出来一个和socket专门和用户通信
    //当有新用户创建或者原来连接用户断开连接,这个方法就会响应
    void onConnection(const TcpConnectionPtr& conn)
    {
        //是否连接成功
        //toip 打印ip toport 打印端口
        if(conn->connected())
        {
            //对端地址信息
            cout << conn->peerAddress().toIpPort() << "->" << conn->localAddress().toIpPort() << "STATE :online" <<endl;
        }
        else
        {
      
            cout << conn->peerAddress().toIpPort() << "->" << conn->localAddress().toIpPort() << "STATE :offline" <<endl;
            //相当于close 释放 socket资源
            conn->shutdown();
            //连接断开,回收资源
            _loop->quit();
        }
        
    }
    //专门处理用户读写事件
    void onMessage(const TcpConnectionPtr& conn,
                    Buffer* buffer,
                    Timestamp time)
                    {
                        /*
                            1.第一个参数是连接,可以通过它读写数据
                            2.缓冲区
                            3.接收到数据的时间细节
                        */
                       //把接收到的全部数据放到字符串中
                       string buf = buffer->retrieveAllAsString();
                       cout << "recv data" << buf << "Time:" << time.toString() << endl;
                       conn->send(buf);
                    }

    TcpServer _server;  //#1 对象需要构造,不指定构造就需要默认构造,没有默认构造,不指定相应的构造就无法创建对象
    /*
    参数有四个 
    1.事件循环EventLoop,       EventLoop* loop                  事件循环Reactor反应堆
    2.绑定的IP地址和端口号,    const InetAddress& listenAddr     IP地址加端口
    3.给TcpServer一个名字,     const string& nameArg            服务器的名字,给线程绑定名字
    4.TCP协议的选项            Option option = kNoReusePort     
    */
    EventLoop* _loop;   //#2 保存事件循环 操作epoll
};

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

    //listenfd 将epoll_ctl添加到epoll上
    server.start();

    //epoll_wait    以阻塞方式等待新用户连接,已连接用户的读写事件
    loop.loop();
    return 0;
}

调试文件

ctrl+shift+b

task.json

{
    "tasks": [
        {
            "type": "shell",
            "label": "g++ build active file",
            "command": "/usr/bin/g++",
            "args": [
                "-g",
                "-std=c++11",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}",
                "-lmuduo_net",
                "-lmuduo_base",
                "-lpthread"
            ],
            "options": {
                "cwd": "/usr/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        }
    ],
    "version": "2.0.0"
}
上一篇:C++类中使用typedef和类中使用枚举类型(muduo日志类中遇到的问题)


下一篇:muduo源码解析30-网络库8:tcpserver类