c++利用mongoose实现http服务

近来在项目中需要实现一个http service的功能。虽然可以通过封装socket自己实现http的发送和解析。但考虑到目前网络上还是有大量的http的解析源码,自己再从头实现一番稍显麻烦。因此在网络上搜刮了一番,看到很多实现http的代码, 无一不体现了其轻量级的特点。然而,虽然轻量级,但从代码的量上来说,为了一个http service的功能,引入这许多的代码,也着实不是十分情愿呢。后在同事的推荐下选择了mongoose的代码。

 

mongoose的代码着实轻量,先看看它的特点:

1. 在整个的实现是使用C语言编写

2. 整个代码也只有一个mongoose.c和mongoose.h两个文件, 从引入第三方的考虑上也着实不多。

3. 实现的功能还是非常多的,从使用的层面上来说功能还是比较全面。只不过不知道是否是为了第三方使用的方便还是怎么地,它的代码只用了两个源文件罢了。诸多的功能也大以宏的开始与结束来区分。

4. 示例非常齐全,所有的功能都有单独的示例

 

然而,不管它实现多少功能,对于我来说只需要三个:

1. 有http的解析等

2. 文件少,使用方便,不需要因为使用一个简单的功能引入大量代码,而且引入的代码着实没有用到。

3. 有完整的示例

 

当我们拿到一个第三方库或者第三方源码的时候,第一件事情就是看看代码的示例,并且自己动手谢谢测试的代码,完成自己想要的功能。于是,我花了一点时间自己写了一个测试的代码,最后发现测试的时候并不通。虽然它的代码示例很全面,然而对于我们来说,或许在它的代码中,有些函数我们不需要,而有些函数却不再这个示例中使用,因此需要自己测试。耗费了一些时间以后,我个人做了一下的简单封装,算是简单的实现一个http service的功能,其中使用到了一点C++11的特性。可丢砖头,也可交流。

 

[cpp]  view plain  copy
 
  1. // File:        basic_http.h  
  2. // Description: ---  
  3. // Notes:       ---  
  4. // Author:      Haust <wyy123_2008@qq.com>  
  5. // Revision:    2015-11-19 by Haust  
  6.   
  7. #pragma once  
  8.   
  9. #include "mongoose.h"  
  10. #include <map>  
  11. #include <string>  
  12. #include <functional>  
  13.   
  14. class BasicHttp {  
  15. public:  
  16.     using handler = std::function<void(std::string, std::string)>;  
  17.   
  18. public:  
  19.     virtual ~BasicHttp(){};  
  20.     
  21.     void Init(uint32_t port);  
  22.     bool Start();  
  23.     bool Close();  
  24.     bool RegisterHandler(std::string uri, handler f);  
  25.     void UnRegisterHandler(std::string uri);  
  26.     void Loop(int milli);  
  27.   
  28.     void SendReply(std::string uri, std::string reply);  
  29.     void SendError(std::string uri, int errcode, std::string reply);  
  30.   
  31. protected:  
  32.     using handler_map = std::map<std::string, handler>;  
  33.     using connection_map = std::multimap<std::string, mg_connection*>;  
  34.   
  35. private:  
  36.     static void EvHandler(struct mg_connection* nc, int ev, void* ev_data);  
  37.     static void HandleRequst(struct mg_connection* nc, int ev, void *ev_data);   
  38.   
  39. public:  
  40.     static handler_map _handlers;  
  41.     static connection_map _connections;  
  42.   
  43.     char _port[11];  
  44.     struct mg_mgr _mgr;  
  45. };  
[cpp]  view plain  copy
 
  1. // File:        basic_http.cpp  
  2. // Description: ---  
  3. // Notes:       ---  
  4. // Author:      Haust <wyy123_2008@qq.com>  
  5. // Revision:    2015-11-19 by Haust  
  6.   
  7. #include "basic_http.h"  
  8.   
  9. BasicHttp::handler_map BasicHttp::_handlers;  
  10. BasicHttp::connection_map BasicHttp::_connections;  
  11.   
  12. void BasicHttp::Init(uint32_t port){  
  13.     memset(_port, 0, sizeof(_port));  
  14.     snprintf(_port, sizeof(_port), "%u", port);  
  15. }  
  16.   
  17. bool BasicHttp::Start(){  
  18.     mg_mgr_init(&_mgr, NULL);  
  19.     auto nc = mg_bind(&_mgr, _port, EvHandler);  
  20.   
  21.     if(nullptr == nc)  
  22.         return false;  
  23.   
  24.     mg_set_protocol_http_websocket(nc);  
  25.     return true;  
  26. }  
  27.   
  28. bool BasicHttp::Close(){  
  29.     mg_mgr_free(&_mgr);  
  30.     return true;  
  31. }  
  32.   
  33. bool BasicHttp::RegisterHandler(std::string uri, handler f){  
  34.     auto it = _handlers.find(uri);  
  35.     if(_handlers.end() != it)  
  36.         return false;  
  37.   
  38.     return _handlers.emplace(uri, f).second;  
  39. }  
  40.   
  41. void BasicHttp::UnRegisterHandler(std::string uri){  
  42.     auto it = _handlers.find(uri);  
  43.     if(_handlers.end() != it)  
  44.         _handlers.erase(it);  
  45. }  
  46.   
  47. void BasicHttp::Loop(int milli){  
  48.     mg_mgr_poll(&_mgr, milli);  
  49. }  
  50.   
  51. void BasicHttp::EvHandler(struct mg_connection* nc, int ev, void* ev_data){  
  52.    switch(ev){  
  53.         case MG_EV_HTTP_REQUEST:  
  54.             HandleRequst(nc, ev, ev_data);  
  55.             break;  
  56.        default:  
  57.            break;  
  58.    }  
  59. }  
  60.   
  61. void BasicHttp::HandleRequst(struct mg_connection *nc, int ev, void* ev_data){  
  62.     http_message* hm = (http_message*)ev_data;  
  63.     std::string uri(hm->uri.p, hm->uri.len);  
  64.   
  65.     auto it = _handlers.find(uri);  
  66.     if(_handlers.end() == it)  
  67.         return;  
  68.   
  69.     _connections.emplace(uri, nc);  
  70.     it->second(std::string(hm->query_string.p, hm->query_string.len),  
  71.             std::string(hm->body.p, hm->body.len));  
  72. }  
  73.   
  74. void BasicHttp::SendReply(std::string uri, std::string reply){  
  75.     auto range = _connections.equal_range(uri);  
  76.     if(range.first == range.second)  
  77.         return;  
  78.   
  79.     auto it = range.first;  
  80.     mg_printf(it->second, "HTTP/1.1 200 OK\r\niConnection: close\r\nContent-Type: text/html\r\nContent-Length: %u\r\n\r\n%s\r\n",   
  81.             (uint32_t)reply.length(), reply.c_str());  
  82.   
  83.     it->second->flags |= MG_F_SEND_AND_CLOSE;  
  84.     _connections.erase(it);  
  85. }  
  86.   
  87. void BasicHttp::SendError(std::string uri, int errcode, std::string reply){  
  88.     auto range = _connections.equal_range(uri);  
  89.     if(range.first == range.second)  
  90.         return;  
  91.   
  92.     auto it = range.first;  
  93.     mg_printf(it->second, "HTTP/1.1 %d %s\r\n", errcode, reply.c_str());  
  94.   
  95.     it->second->flags |= MG_F_SEND_AND_CLOSE;  
  96.     _connections.erase(it);  
  97. }  
  98.   
  99. #include "mongoose.c" 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值