cppweb框架介绍

作者

chenxuan

dog

创作初衷

自己在搭建C++服务器的时候发现,boost库太庞大对新手不够友好,libevent应用于专业化对新人不友好,用c++开发http后端十分繁琐而且代码复用率低,在使用go的gin框架的时候 ,就萌发了自己写一个类似后端轻量库和简易服务器的想法

官方网站

http://cpp.androidftp.top

框架特点

项目结构

项目特点

  1. 使用C++编写,拥有较快的运行速度

  2. 支持使用自定义中间件

  3. 支持cookie的生成和读取

  4. 包含一个json的解析生成格式化库(也是作者写的)

  5. 包含email类,可以调用发送邮件

  6. 支持通过路由管理请求

    支持lam表达式

  7. 支持日志生成和实现,日志系统约为30万条每秒

  8. 具有io复用,多进程,线程池三种模式

    io复用支持epoll(epoll只支持linux)和select模型

  9. 包含线程池和线程池服务器

  10. 支持https连接

    包括服务端和客户端

  11. 自带由框架编写的服务器

    1. 支持路由301转发

    2. 支持反向代理,负载均衡

    负载均衡支持轮询,随机,哈希,等四种方式

    1. 支持路径的替换

    2. 通过json配置,自定义程度高

    3. 自带守护进程和后台运行,宕机快速重启

项目说明

搭建服务器

框架介绍

服务器运行

安装框架

简单使用

#include "../../hpp/cppweb.h"//包含头文件
using namespace cppweb;
int main()  
{  
    HttpServer server(5200,true);//输入运行端口以及是否开启打印的调试模式
    server.run("index.html");//输入访问路径为 / 时默认文件,没有可以不填
    return 0; //没有错会一直运行,除非出错,可以用lastError获取错取
}  

搭建https

#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;
}

路由设置

    server.get("/lam*",[](HttpServer&,DealHttp& http,int)->void{
        http.gram.body="text";//设置报文内容
    });

中间件设置

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; 
}  

设置cookie

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");

速度测试

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

更多文档

感谢支持


个人官网 个人简历

gitee github

(个人网站均运行在该框架之上)


如果你喜欢这个项目,可以给一个⭐