开源C++ http服务框架WHttpServer

WHttpServer

gitee地址:https://gitee.com/fengxian21/whttp-server/

介绍

基于mongoose 7.3版本的源码,修改源码及二次封装,引入线程池编写的http服务,同时支持https。
使用示例可以查看HttpExample.cpp、HttpExample.h和main.cpp三个文件,里面分别举例了http普通接口、大文件上传、大文件下载3个典型场景。

操作系统:Linux

安装教程

直接将whttp-server-core目录里面的文件拷贝到自己的工程即可

接口说明
  1. bool init(int maxEventThreadNum),初始化线程池,指定线程池最大线程数
  2. bool startHttp(int port),开启http服务
  3. bool startHttps(int port, string certPath, string keyPath),开启https服务
  4. bool stop(),停止http和https服务,在析构函数函数里面已经调用
  5. bool run(),服务运行的发动机,外部必须用一个死循环一直调用该函数
  6. bool isRunning(),查看服务是否还在运行中
  7. void addHttpApi(const string &uri, HttpCbFun fun, int httpMethods),添加普通的http回调接口,其中httpMethods以数据的不同位职位代表不同的http方法,具体如下:
         #define W_HTTP_GET      (1 << 0)
         #define W_HTTP_POST     (1 << 1)
         #define W_HTTP_PUT      (1 << 2)
         #define W_HTTP_DELETE   (1 << 3)
         #define W_HTTP_HEAD     (1 << 4)
         #define W_HTTP_ALL       0xFF
  1. void addChunkHttpApi(const string &uri, HttpCbFun fun, int httpMethods),添加数据块http回调接口,当客户端的http请求数据可能超过3M时,采用这个函数添加接口,典型的场景如文件上传
  2. void setHttpFilter(HttpFilterFun filter),设置http接口的过滤函数,若过滤函数filter返回false,则不会进入回调,用于需要如登录信息才会响应的接口
  3. void forceCloseHttpConnection(shared_ptr httpMsg),用于强行关闭socket连接,正常情况下,回调完成后,框架内部会自己关闭socket连接。但是有些情况下,比如文件下载时,客户端暂停了下载,而且暂停时间很久,这就导致服务器的某个线程的任务一直被卡主,不得不强制关闭socket
  4. void addSendMsgToQueue(shared_ptr httpMsg, const char* data, int len),向客户端返回数据,会先放入缓冲区,等待下次循环时再发送出去
  5. void addSendMsgToQueue(shared_ptr httpMsg, string *sendMsg),向客户端返回数据,上面函数的重载
  6. void httpReplyJson(shared_ptr httpMsg, int httpCode, string head, string body),向客户端返回数据,返回type是json,这是对上面2个函数进一步封装的便捷函数
  7. string formJsonBody(int code, string message),返回类似{“code”:0, “message”: “success”}的json字符串
  8. bool isClientDisconnect(shared_ptr httpMsg),返回客户端是否主动断开了连接
  9. shared_ptr deQueueHttpChunk(shared_ptr httpMsg),大文件上传的场景,获取chunk数据块
  10. bool addStaticWebDir(const string &dir, const string &header = “”),新增接口,用于形成web容器目录,可部署网页
重要数据类型
  1. using HttpCbFun = std::function<void(shared_ptr &)>,http接口的回调函数
  2. using HttpFilterFun = std::function<bool(shared_ptr &)>,http接口的过滤函数
  3. HttpReqMsg结构体
 struct HttpReqMsg
{
   mg_connection *httpConnection = nullptr; // mongoose里面代表一个socket连接的结果体,外层不关心
   string method; // http方法,可以是GET POST PUT DELETE等
   string uri; 
   map<string, string> querys; // the params in uri
   string proto; // http version
   map<string, string, WCaseCompare> headers; // http头部字段,其中key是大小写不敏感的,比如"Content-Length" 和 "content-length"是一个效果
   string body; // http body体数据
   int64_t totalBodySize; // http body体数据大小,就是头部"content-length"值
   shared_ptr<HttpChunkQueue> chunkQueue; // 大文件上传时,存储文件的数据块
   shared_ptr<HttpSendQueue> sendQueue; // http返回给客户端的数据队列
   int64_t recvChunkSize = 0; // 大文件上传时,已经接收到的数据块大小
   bool finishRecvChunk = false; // 大文件上传时,判断是否所有数据都上传完成了
};
注意事项

1、所有http回调函数都是在子线程里面运行的,即使同一个回调函数,每次运行也不一定在一个线程,注意线程安全
2、为了保证更好的性能,发动机函数run里面没有加锁,不是线程安全的,所以初始化之类的函数,如init、startHttp、addHttpApi之类的函数的调用需要在启动run函数之前运行,或者其和run函数在一个线程
3、addHttpApi和addChunkHttpApi函数给uri时,不要给可能重复匹配的uri,否则只有1个生效。比如给“/test”和”/test/dotest“这样的,因为当uri是”/test/dotest“时,“/test”也是可以匹配成功,我认为这种情况属于uri没有设计好,不想像node.js一样提供next函数处理这种情况。若你uri直接给‘/’,那么估计所有的回调全都会进‘/’的回调函数中

示例代码

初始化代码:

void HttpExample::start()
{
    _httpServer = new WHttpServer();
    _httpServer->init(32);
    HttpFilterFun filterFun = std::bind(&HttpExample::httpFilter, this, std::placeholders::_1);
    _httpServer->setHttpFilter(filterFun);
    _httpServer->startHttp(6200);

    HttpCbFun normalCbFun = std::bind(&HttpExample::handleHttpRequestTest, this, std::placeholders::_1);
    _httpServer->addChunkHttpApi("/whttpserver/test", normalCbFun, W_HTTP_GET);

    HttpCbFun bigFileUploadCbFun = std::bind(&HttpExample::handleHttpBigFileUpload, this, std::placeholders::_1);
    _httpServer->addChunkHttpApi("/whttpserver/bigfileupload", bigFileUploadCbFun, W_HTTP_POST | W_HTTP_PUT);

    HttpCbFun downloadFileCbFun = std::bind(&HttpExample::handleHttpDownloadFile, this, std::placeholders::_1);
    _httpServer->addChunkHttpApi("/whttpserver/downloadFile/", downloadFileCbFun, W_HTTP_GET | W_HTTP_HEAD);
}

在main函数中启动发动机:

while(true)
{
    httpTest.run();
}

http接口回调示例代码:

void HttpExample::handleHttpRequestTest(shared_ptr<HttpReqMsg> &httpMsg)
{
    // You can add http headers like below
    stringstream sstream;
    sstream << "Access-Control-Allow-Origin: *" << "\r\n";
    _httpServer->httpReplyJson(httpMsg, 200, sstream.str(), _httpServer->formJsonBody(0, "success"));
    // _httpServer->httpReplyJson(httpMsg, 200, "", _httpServer->formJsonBody(0, "success"));
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C 开源游戏服务框架是一种能够帮助开发者构建和运行多人在线游戏服务器的工具。它提供了一组功能强大的库和工具,可以简化游戏服务器的开发过程。 首先,C 开源游戏服务框架具有高度的可定制性和灵活性。开发者可以根据自己的需求和喜好,选择合适的组件和功能来构建游戏服务器。这使得开发者能够更好地控制服务器的性能、功能和安全性。 其次,C 开源游戏服务框架具备高度的可扩展性。它采用模块化设计,开发者可以根据需要增加新的功能,或者替换已有的组件,来满足不同的游戏需求。这个特点使得框架能够应对不同类型的游戏和不同规模的服务器。 另外,C 开源游戏服务框架具有高效的性能。它采用了优化的算法和数据结构,能够在处理大量玩家同时在线的情况下,保持服务器的稳定性和响应速度。这一特点对于多人在线游戏来说尤为重要,可以确保玩家之间的实时互动和游戏体验。 最后,C 开源游戏服务框架拥有活跃的社区和丰富的资源。开发者可以在社区中寻求技术支持、分享经验和获取最新的更新。同时,社区还提供了大量的教程、文档和示例代码,方便开发者学习和使用框架。 综上所述,C 开源游戏服务框架是一种功能强大、可定制、可扩展和高性能的工具,对于开发多人在线游戏服务器具有重要意义。它为开发者提供了便利和灵活性,使得他们能够更好地构建和管理游戏服务器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值