具备简单的集成性基础功能。
模块架构:
- acc(接受请求)
- rsc(响应+调度器实现)
- RESRC(资源池)https://github.com/yauntyour/RESRC
- com(中心封装和集成)
全部二次封装&集成&C++ class封装于appweb.h。
#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;
}#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,其结构为
/* 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();//删除冗余内存
-
使用
app.start(flag_wait);执行服务。执行端会监听您提供的port。flag设置为0表示默认阻塞运行。 -
使用
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;-
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
-
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
g++ -g XXXX.cpp -o XXXX -fexec-charset=UTF-8 -lwsock32 -lpthread
g++ -g XXXX.cpp -o XXXX -fexec-charset=UTF-8 -lpthread
