chenxuan
自己在搭建C++服务器的时候发现,boost库太庞大对新手不够友好,libevent应用于专业化对新人不友好,用c++开发http后端十分繁琐而且代码复用率低,在使用go的gin框架的时候 ,就萌发了自己写一个类似后端轻量库和简易服务器的想法
具有Linux和windows跨平台特点
跨平台说明
在windows平台下支持clang和MinGW,不支持mscv(
因为作者不喜欢)在linux平台支持clang和gcc
在mac平台没有进行测试(
因为作者没有mac)
扩展性好,自由订制处理http响应
安装方便,核心只有hpp/cppweb.h一个头文件
学习成本低,半个小时就可掌握用法
文档详细中文 ,代码全部开源
轻量级,核心代码只有一个头文件,代码不到5000行,可直接使用头文件操作
使用C++编写,拥有较快的运行速度
支持使用自定义中间件
支持cookie的生成和读取
包含一个json的解析生成格式化库(也是作者写的)
包含email类,可以调用发送邮件
支持通过路由管理请求
支持lam表达式
支持日志生成和实现,日志系统约为30万条每秒
具有io复用,多进程,线程池三种模式
io复用支持epoll(epoll只支持linux)和select模型
包含线程池和线程池服务器
支持https连接
包括服务端和客户端
自带由框架编写的服务器
支持路由301转发
支持反向代理,负载均衡
负载均衡支持轮询,随机,哈希,等四种方式
支持路径的替换
通过json配置,自定义程度高
自带守护进程和后台运行,宕机快速重启
#include "../../hpp/cppweb.h"//包含头文件
using namespace cppweb;
int main()
{
HttpServer server(5200,true);//输入运行端口以及是否开启打印的调试模式
server.run("index.html");//输入访问路径为 / 时默认文件,没有可以不填
return 0; //没有错会一直运行,除非出错,可以用lastError获取错取
}
#define CPPWEB_OPENSSL
#include "../../hpp/cppweb.h"
using namespace std;
using namespace cppweb;
int main()
{
HttpServer server(5201,true,HttpServer::THREAD,5);
server.loadKeyCert("./cacert.pem","./privkey.pem","123456");
//第一个是证书位置,第二个是私钥位置,第三个是密码(没有可以不填)
server.run("./index.html");
return 0;
}
需要安装openssl
需要包含头文件之前定义宏
server.get("/lam*",[](HttpServer&,DealHttp& http,int)->void{
http.gram.body="text";//设置报文内容
});
支持lam表达式和普通函数
支持路由的*扩展
void pfunc(HttpServer& server,DealHttp& http,int soc)
{
http.head["try"]="en";
server.continueNext(soc);//继续执行后面默认操作,也可以不执行
}
int main()
{
HttpServer server(5200,true);
server.setMiddleware(pfunc);//设置中间件
server.get("/root",[](HttpServer&,DealHttp& http,int){
http.gram.body="text";
});
server.run("./index.html");
return 0;
}
server.setLog(LogSystem::recordRequest,NULL);
server.get("/stop",[](HttpServer& server,DealHttp&,int){
server.stopServer();
});
void func(HttpServer& server,DealHttp& http,int)
{
DealHttp::Request req;
http.analysisRequest(req,server.recText());
printf("old:%s\n",(char*)server.recText());
printf("new:%s %s %s\n",req.method.c_str(),req.askPath.c_str(),req.version.c_str());
for(auto iter=req.head.begin();iter!=req.head.end();iter++)
printf("%s:%s\n",iter->first.c_str(),iter->second.c_str());
printf("body:%s\n",req.body);
http.gram.statusCode=DealHttp::STATUSOK;
http.gram.typeFile=DealHttp::JSON;
http.gram.body="{\"ha\":\"ha\"}";
}
int main()
{
HttpServer server(5200,true);//input the port bound
server.all("/root",func);
server.run("./index.html");
if(server.lastError()!=NULL)
{
std::cout<<server.lastError()<<std::endl;
return -1;
}
return 0;
}
void cookie(HttpServer& server,DealHttp& http,int)
{
char buffer[100]={0};
http.getCookie(server.recText(),"key",buffer,100);
if(strlen(buffer)==0)
{
http.gram.body="ready to setting cookie";
http.gram.cookie["key"]=http.designCookie("cookie ok",10);
return;
}
Json json={
{"key",(const char*)buffer},
{"status","ok"}
};
http.gram.body=json();
http.gram.typeFile=DealHttp::JSON;
}
int main()
{
HttpServer server(5200,true);
server.get("/cookie",cookie);
server.run("index.html");
return 0;
}
ClientTcpIp client(ip,port);
if(client.lastError()!=NULL)
{
printf("error%s\n;",client.lastError());
exit(0);
}
DealHttp http;
DealHttp::Request req;
req.head.insert(pair<string,string>{"Host",topUrl});
req.askPath=endUrl;
req.method="GET";
req.version="HTTP/1.1";
char buffer[500]={0},rec[5000]={0};
http.createAskRequest(req,buffer,500);
if(!isHttps)
{
if(false==client.tryConnect())
{
printf("connect wrong\n");
exit(0);
}
if(0>client.sendHost(buffer,strlen(buffer)))
{
printf("%d",errno);
exit(0);
}
client.receiveHost(rec,5000);
}
else
{
if(false==client.tryConnectSSL())
{
printf("connect wrong\n");
exit(0);
}
if(0>client.sendHostSSL(buffer,strlen(buffer)))
{
printf("%d",errno);
exit(0);
}
client.receiveHostSSL(rec,5000);
}
HttpServer server(5200,true);
server.loadStatic("/file/index.html","index.html");
server.loadStatic("/try/*","test");
server.deletePath("test");
使用http_load测试,每秒1000个连接,持续15s
开启日志状态下
比较对象为nginx,go的gin框架
nginx server
1833 fetches, 1000 max parallel, 1.1218e+06 bytes, in 15 seconds
612 mean bytes/connection
122.2 fetches/sec, 74786.4 bytes/sec
msecs/connect: 248.187 mean, 14454.9 max, 21.731 min
msecs/first-response: 349.369 mean, 13968.4 max, 21.556 min
HTTP response codes:
code 200 -- 1833
gin server
1528 fetches, 1000 max parallel, 921384 bytes, in 15.0002 seconds
603 mean bytes/connection
101.865 fetches/sec, 61424.9 bytes/sec
msecs/connect: 731.15 mean, 11533.5 max, 21.645 min
msecs/first-response: 319.711 mean, 7317.47 max, 21.518 min
HTTP response codes:
code 200 -- 1528
my server
1792 fetches, 1000 max parallel, 1.1433e+06 bytes, in 15.0001 seconds
638 mean bytes/connection
119.466 fetches/sec, 76219.1 bytes/sec
msecs/connect: 143.062 mean, 7316.08 max, 21.651 min
msecs/first-response: 334.025 mean, 13735.1 max, 21.481 min
HTTP response codes:
code 200 -- 1792
(个人网站均运行在该框架之上)
如果你喜欢这个项目,可以给一个⭐