GithubHelp home page GithubHelp logo

owent / libatapp Goto Github PK

View Code? Open in Web Editor NEW
20.0 5.0 12.0 1.47 MB

server app framework based on libatbus

License: MIT License

CMake 3.37% C++ 92.87% C 1.32% PowerShell 0.57% Shell 1.86%
gcc gitter framework app server performance linux windows cxx cpp distributed-systems osx macos

libatapp's Introduction

libatapp

用于搭建高性能、全异步(a)的跨平台应用框架库。

ci-badge

CI Job Matrix

Target System Toolchain Note
Linux GCC
Linux Clang With libc++
Linux GCC 4.8
MinGW64 GCC Dynamic linking
Windows Visual Studio 2022 Dynamic linking
Windows Visual Studio 2022 Static linking
Windows Visual Studio 2019 Static linking
macOS AppleClang With libc++

依赖

  • 支持c++0x或c++11的编译器(为了代码尽量简洁,特别是少做无意义的平台兼容,依赖部分 C11和C++11的功能,所以不支持过低版本的编译器)

    • GCC: 4.8 及以上
    • Clang: 3.8 及以上
    • VC: 14 及以上
  • cmake 3.16.0 以上

GET START

最小化服务器

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>

#include <uv.h>

#include <atframe/atapp.h>
#include <common/file_system.h>

static int app_handle_on_msg(atapp::app &app, const atapp::app::message_sender_t& source, const atapp::app::message_t &msg) {
    std::string data;
    data.assign(reinterpret_cast<const char *>(msg.data), msg.data_size);
    FWLOGINFO("receive a message(from {:#x}, type={}) {}", source.id, msg.type, data);

    return app.get_bus_node()->send_data(source.id, msg.type, msg.data, msg.data_size);
}

static int app_handle_on_response(atapp::app & app, const atapp::app::message_sender_t& source, const atapp::app::message_t & msg, int32_t error_code) {
    if (error_code < 0) {
        FWLOGERROR("send data from {:#x} to {:#x} failed, sequence: {}, code: {}", app.get_id(), source.id, msg.msg_sequence, error_code);
    } else {
        FWLOGDEBUG("send data from {:#x} to {:#x} got response, sequence: {}", app.get_id(), source.id, msg.msg_sequence);
    }
    return 0;
}

int main(int argc, char *argv[]) {
    atapp::app app;

    // 设置工程目录,不设置的话日志打印出来都是绝对路劲,比较长
    {
        std::string proj_dir;
        util::file_system::dirname(__FILE__, 0, proj_dir, 2); // 设置当前源文件的2级父目录为工程目录
        util::log::log_formatter::set_project_directory(proj_dir.c_str(), proj_dir.size());
    }

    // setup handle
    app.set_evt_on_forward_request(app_handle_on_msg);         // 注册接收到数据后的回调
    app.set_evt_on_forward_response(app_handle_on_response);   // 注册发送消息失败的回调

    // run with default loop in libuv
    return app.run(uv_default_loop(), argc, (const char **)argv, nullptr);
}

设置自定义命令行参数

// ...

#include <sstream>

static int app_option_handler_echo(util::cli::callback_param params) {
    // 获取参数并输出到stdout
    std::stringstream ss;
    for (size_t i = 0; i < params.get_params_number(); ++i) {
        ss << " " << params[i]->to_cpp_string();
    }

    std::cout << "echo option: " << ss.str() << std::endl;
    return 0;
}

int main(int argc, char *argv[]) {
    atapp::app app;
    // ...
    // setup options, 自定义命令行参数是区分大小写的
    util::cli::cmd_option::ptr_type opt_mgr = app.get_option_manager();
    // show help and exit
    opt_mgr->bind_cmd("-echo", app_option_handler_echo)   // 当启动参数里带-echo时跳转进 app_option_handler_echo 函数
        ->set_help_msg("-echo [text]                           echo a message."); // 帮助文本,--help时显示,不执行这个就没有帮助信息

    // ...
    // run
    return app.run(uv_default_loop(), argc, (const char **)argv, nullptr);
}

设置自定义远程命令

// ...
#include <sstream>

static int app_command_handler_echo(util::cli::callback_param params) {
    std::stringstream ss;
    for (size_t i = 0; i < params.get_params_number(); ++i) {
        ss << " " << params[i]->to_cpp_string();
    }

    WLOGINFO("echo commander:%s", ss.str().c_str());
    return 0;
}

int main(int argc, char *argv[]) {
    atapp::app app;
    // ... 
    // setup cmd, 自定义远程命令是不区分大小写的
    util::cli::cmd_option_ci::ptr_type cmgr = app.get_command_manager();
    cmgr->bind_cmd("echo", app_command_handler_echo)
        ->set_help_msg("echo       [messages...]                                    echo messages to log");

    // 然后就可以通过 [EXECUTABLE] -id ID --conf CONFIGURE_FILE run echo MESSAGES ... 来发送命令到正在运行的服务器进程了
    // ...

    // run
    return app.run(uv_default_loop(), argc, (const char **)argv, nullptr);
}

自定义模块

// ...

// 自定义模块必需继承自atapp::module_impl
class echo_module : public atapp::module_impl {
public:
    virtual int init() {
        // 初始化时调用,整个app的生命周期只会调用一次
        // 初始化时这个调用再reload只会,这样保证再init的时候配置时可用的
        WLOGINFO("echo module init");
        return 0;
    };

    virtual int reload() {
        // 重新加载配置时调用
        WLOGINFO("echo module reload");
        return 0;
    }

    virtual int stop() {
        // app即将停止时调用,返回非0值表示需要异步回收数据,这时候等回收完成后需要手动再次调用atapp的stop函数
        WLOGINFO("echo module stop");
        return 0;
    }

    virtual int timeout() {
        // stop超时后调用,这个返回以后这个模块会被强制关闭
        WLOGINFO("echo module timeout");
        return 0;
    }

    virtual const char *name() const { 
        // 返回模块名,如果不重载会尝试使用C++ RTTI特性判定,但是RTTI生成的符号名称可能不是很易读
        return "echo_module"; 
    }

    virtual int tick() {
        // 每次tick的时候调用,tick间隔由配置文件指定,返回成功执行的任务数
        time_t cur_print = util::time::time_utility::get_sys_now() / 20;
        static time_t print_per_sec = cur_print;
        if (print_per_sec != cur_print) {
            WLOGINFO("echo module tick");
            print_per_sec = cur_print;
        }

        // 返回值大于0时,atapp会认为模块正忙,会很快再次调用tick
        // 这样可以阻止atapp进入sleep
        return 0;
    }
};

int main(int argc, char *argv[]) {
    atapp::app app;
    // ... 
    // setup module, 自定义模块必需是shared_ptr
    app.add_module(std::make_shared<echo_module>());
    // ...

    // run
    return app.run(uv_default_loop(), argc, (const char **)argv, nullptr);
}

更多的细节请参照 sample

libatapp's People

Contributors

owent avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.