Skip to content

yauntyour/appweb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

appweb (v3.0)

具备简单的集成性基础功能。

模块架构:

全部二次封装&集成&C++ class封装于appweb.h

详细内容

example.cpp dome

#include <iostream>
#include <stdio.h>
#include <time.h>
#include "appweb.h"

static RESRC res;

FUNC_CB_C(api)
{
    printf("%s\r\n", req->data.data);
    return "{'test':'Hello,World'}";
};

FUNC_CB_C(POST_TEST)
{
#ifdef _WIN32
    RESRC_FILE *p = RESRC_select_path(&res, "D:\\Dev\\appweb\\out\\post_test.html");
#else
    RESRC_FILE *p = RESRC_select_path(&res, "/workspaces/appweb/out/post_test.html");
#endif
    return p->data.data;
};

FUNC_CB_C(test)
{
    return "<h1 style='text-align:center;'>Hello,World</h1>";
};

FUNC_CB_C(img)
{
    // 在func内部使用send()需要使用func_CB_OUT,因为需要一个“\r\n”字符来终止标头
#ifdef _WIN32
    RESRC_FILE *p = RESRC_select_path(&res, "D:\\Dev\\appweb\\out\\image.jpg");
#else
    RESRC_FILE *p = RESRC_select_path(&res, "/workspaces/appweb/out/image.jpg");
#endif
    FUNC_CB_OUT(req->addr.socket, p->data.data, p->data.length, 0);
    // 返回包含“\0”是第一个字符的结果的字符串
    return "";
}
void *func(void *arg)
{
#ifdef _WIN32
    system("dir");
#else
    system("ls -a");
#endif
    return NULL;
}

#ifdef _WIN32
static FILE_PATH file_list[] = {
    {"D:\\Dev\\appweb\\out\\post_test.html", "rb"},
    {"D:\\Dev\\appweb\\out\\image.jpg", "rb"},
    {NULL, NULL}};
#else
static FILE_PATH file_list[] = {
    {"/workspaces/appweb/out/post_test.html", "rb"},
    {"/workspaces/appweb/out/image.jpg", "rb"},
    {NULL, NULL}};
#endif //_WIN32

int main(int argc, char const *argv[])
{
    LOG_LIGHT_NF("%s\n", "Build application by Yauntyour (https://github.com/yauntyour) with C++");
    RESRC_load_filelist(&res, file_list, 2);
#ifdef _WIN32
    WS_Init();
#endif
    appweb app(8, 10000, 3);
    app.set_root_dict_func(test, Type_ALL, "text/html");
    Varde home_list[] = {
        Varde_def(POST_TEST, Type_GET, "postTest", COMPATH_True, "text/html"),
        Varde_def(api, Type_POST, "api", COMPATH_True, "application/json"),
        Varde_def(img, Type_GET, "img", COMPATH_True, "image/png"),
    };
    Varde home_dict[] = {
        {test, Type_GET, "home", home_list, 3, 3, COMPATH_True, "text/html"},
        {test, Type_GET, "index", home_list, 3, 3, COMPATH_True, "text/html"}};
    app.root_dict_p->list_append(home_dict, sizeof(home_dict) / sizeof(Varde));
    app.root_dict_p->ZIP();

    app.add_event(func, NULL);
    app.start(flag_wait);
#ifdef _WIN32
    WS_clean();
#endif
    for (size_t i = 0; file_list[i].path == NULL; i++)
    {
        RESRC_free(&(res.filelist[i]));
        RESRC_FILE_CLOSE(&(res.filelist[i]));
    }
    return 0;
}

example.c dome

#include <stdio.h>
#include <time.h>
#include "appweb.h"

static RESRC res;

FUNC_CB_C(api)
{
    printf("%s\r\n", req->data.data);
    return "{'test':'Hello,World'}";
};
FUNC_CB_C(POST_TEST)
{
#ifdef _WIN32
    RESRC_FILE *p = RESRC_select_path(&res, "D:\\Dev\\appweb\\out\\post_test.html");
#else
    RESRC_FILE *p = RESRC_select_path(&res, "/workspaces/appweb/out/post_test.html");
#endif
    return p->data.data;
};
FUNC_CB_C(test)
{
    return "<h1 style='text-align:center;'>Hello,World</h1>";
};
FUNC_CB_C(img)
{
    // 在func内部使用send()需要使用func_CB_OUT,因为需要一个“\r\n”字符来终止标头
#ifdef _WIN32
    RESRC_FILE *p = RESRC_select_path(&res, "D:\\Dev\\appweb\\out\\image.jpg");
#else
    RESRC_FILE *p = RESRC_select_path(&res, "/workspaces/appweb/out/image.jpg");
#endif
    FUNC_CB_OUT(req->addr.socket, p->data.data, p->data.length, 0);
    // 返回包含“\0”是第一个字符的结果的字符串
    return "";
}

void *func(void *arg)
{
#ifdef _WIN32
    system("dir");
#else
    system("ls -a");
#endif
    return NULL;
}

#ifdef _WIN32
static FILE_PATH file_list[] = {
    {"D:\\Dev\\appweb\\out\\post_test.html", "rb"},
    {"D:\\Dev\\appweb\\out\\image.jpg", "rb"},
    {NULL, NULL}};
#else
static FILE_PATH file_list[] = {
    {"/workspaces/appweb/out/post_test.html", "rb"},
    {"/workspaces/appweb/out/image.jpg", "rb"},
    {NULL, NULL}};
#endif //_WIN32

int main(int argc, char const *argv[])
{
    LOG_LIGHT_NF("%s\n", "Build application by Yauntyour (https://github.com/yauntyour) with C");
    RESRC_load_filelist(&res, file_list, 2);
#ifdef _WIN32
    WS_Init();
#endif
    appev_t ev;
    ev.port = 10000;
    ev.UTCoffset = 8;
    // UDP_CONNECT or TCP_CONNECT
    ev.connect_type = TCP_CONNECT; // Use TCP connection
    // ev.connect_type = UDP_CONNECT;

    app_event_init(&ev, 128);

    // root event
    set_root_dict_func(&ev, test, Type_ALL, "text/html");
    // root list
    ev.root_dict.list_length = 0;
    ev.root_dict.list_size = 0;
    ev.root_dict.list = NULL;

    Varde home_list[] = {
        Varde_def(POST_TEST, Type_GET, "postTest", COMPATH_True, "text/html"),
        Varde_def(api, Type_POST, "api", COMPATH_True, "application/json"),
        Varde_def(img, Type_GET, "img", COMPATH_True, "image/png"),
    };
    Varde home_dict[] = {
        {test, Type_GET, "home", home_list, 3, 3, COMPATH_True, "text/html"},
        {test, Type_GET, "index", home_list, 3, 3, COMPATH_True, "text/html"}};

    Varde_list_append(&(ev.root_dict), home_dict, sizeof(home_dict) / sizeof(Varde));
    Varde_ZIP(&(ev.root_dict));

    // set a event func out of server
    ev.event_func = func;

    pthread_t acc_th;
    app_acc(&acc_th, &ev);
    pthread_join(acc_th, NULL);
#ifdef _WIN32
    WS_clean();
#endif
    for (size_t i = 0; file_list[i].path == NULL; i++)
    {
        RESRC_free(&(res.filelist[i]));
        RESRC_FILE_CLOSE(&(res.filelist[i]));
    }
    return 0;
}

基本使用

Varde 的基本原理和结构————树级目录

  1. 注册一个Varde,其结构为

    /*
            necessary arg:
                char* Name :node's Name;
                func_cb func :A deal by function;
                int req_Type :request model;
                struct varde *list :A node list this node;
                size_t list_length, list_size :The list's length & size;
                int ComPath :Common path resolution:true or false;
            if req_model == -1,it will disable this Varde;
           */
        typedef struct varde
        {
            func_cb func;
            int req_Type;
            char *Name; // The Name of varde
            struct varde *list;
            size_t list_length;
            size_t list_size;
            int ComPath; // Common path resolution:true or false
            char *resp_mime_type;
    #ifdef __cplusplus
            int append(struct varde *Var);
            int ZIP();
            int list_append(struct varde *dict, size_t len);
    #endif //__cplusplus
        } Varde;
    
    //函数类型为:
    typedef char *(*func_cb)(req_t *, bytes *);
    //利用该宏可以快速定义一个标准函数(参见example dome)
    #define FUNC_CB_C(__name__) char *__name__(req_t *req, bytes *header)
    //显然我们可以通过bytes组件库提供的操作函数为header添加内容。
    //但是要注意,header尚未调用bytes_create。
    //理论上根据规范,您只需要返回页面的内容,调度器会自动写入响应流的末尾。
    
    //如果你要在定义的FUNC_CB里使用内容输出:请使用这个宏
    #define FUNC_CB_OUT(__arg__...) send(req->addr.socket, "\r\n",2, 0);send(__arg__) 
    //就像这样:
    FUNC_CB_C(img)
    {
        // 在func内部使用send()需要使用func_CB_OUT,因为需要一个“\r\n”字符来终止标头
        RESRC_FILE *p = RESRC_select_path(&res, "K:\\CCXXProgram\\appweb\\out\\bg.jpg");
        FUNC_CB_OUT(req->addr.socket, p->data.data, p->data.length, 0);
        // 返回包含“\0”是第一个字符的结果的字符串
        return "";
    }

    我们提供一个快捷注册的宏

    #define Varde_def(func, req_Type, Name, ComPath)  \
        {                                             \
            func, req_Type, Name, NULL, 0, 0, ComPath \
        }
    //eg: Varde var = Varde_def(test,req_ALL,"test",COMPATH_True);

    同时可以使用append(struct varde *Var)list_append(struct varde *dict, size_t len)函数便捷地添加Varde节点或是直接追加Varde列表。

    app.set_root_dict_func(test, Type_ALL, "text/html");
    Varde home_list[] = {
    	Varde_def(POST_TEST, Type_GET, "postTest", COMPATH_True, "text/html"),
        Varde_def(api, Type_POST, "api", COMPATH_True, "application/json"),
        Varde_def(img, Type_GET, "img", COMPATH_True, "image/png"),
    };
    Varde home_dict[] = {
       	{test, Type_GET, "home", home_list, 3, 3, COMPATH_True, "text/html"},
        {test, Type_GET, "index", home_list, 3, 3, COMPATH_True, "text/html"}};
    app.root_dict_p->list_append(home_dict, sizeof(home_dict) / sizeof(Varde));//追加列
    app.root_dict_p->ZIP();//删除冗余内存
  2. 使用app.start(flag_wait);执行服务。执行端会监听您提供的port。flag设置为0表示默认阻塞运行。

  3. 使用app.add_event(func, NULL);为程序添加额外的事件服务函数。

    void *func(void *arg)
    {
    #ifdef _WIN32
        system("dir");
    #else
        system("ls -a");
    #endif
        return NULL;
    }
    app.add_event(func, NULL);//添加事件函数,会在acc线程执行后执行此线程

    可以在开启服务器的同时,额外注册一个线程执行自定义的内容,例如启动SQL服务、Python脚本等等。

相关基础信息

typedef struct appev
{
    IPv4_addr_t tcpip, udpip;
    unsigned int port;
    Varde root_dict;
    size_t MAXCONNECT;
    int UTCoffset;
    int connect_type; // 0:TCP, 1:UDP, 2:ALL
    void *(*event_func)(void *arg);//事件注册函数
    void *arg;//参数指针
    pthread_t event_th;
} appev_t;

SDK&Debug&Python实现的调试工具

  1. nc.py

    #参数
    if sys.argv[1] == '-nc':
        netcat()
    elif sys.argv[1] == '-cli':
        UDPclientSend()
    elif sys.argv[1] == '-server':
        Server()
    else:
        print("no this mode")
        print("argv format: -mode host port recvbufflen/data (Server socketTypes:STREAM/DGRAM)")
    ##argv format: -mode host port recvbufflen/data (Server socketTypes:STREAM/DGRAM)
    #eg :python nc.py -cli 127.0.0.1 10000 1280 STREAM
  2. netools.py

    #可以自行修改msg的内容
    msg = "GET /home HTTP/1.1\r\nHost: localhost\r\nUser-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2\r\n\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8\r\nAccept-Language: zh-cn,zh;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nReferer: http://localhost/\r\nContent-Length: 25\r\nContent-Type: application/x-www-form-urlencoded\r\nusername=aa&password=1234"
    
    if sys.argv[1] == '-nc':
        netcat()
    else:
        print("argv format: -mode host port recvbufflen")
    #argv format: -mode host port recvbufflen

关键的依赖库

Windows下使用appweb库看起来这样(Windows下socket 需要 wsock32.lib)

g++ -g XXXX.cpp -o XXXX -fexec-charset=UTF-8 -lwsock32 -lpthread

Linux下使用appweb库看起来是这样的

g++ -g XXXX.cpp -o XXXX -fexec-charset=UTF-8 -lpthread

只需包含根目录下的appweb.h(C/C++完全封装)即可调用此库

Made by yauntyour Copyright reserved

Copyright see the file LICENSE

About

appweb 开源执行端框架 具备集成的功能 性能极佳

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published