c++利用mongoose實現http服務

來源:互聯網
上載者:User

近來在項目中需要實現一個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的特性。可丟磚頭,也可交流。

// File:        basic_http.h// Description: ---// Notes:       ---// Author:      Haust <wyy123_2008@qq.com>// Revision:    2015-11-19 by Haust#pragma once#include "mongoose.h"#include <map>#include <string>#include <functional>class BasicHttp {public:    using handler = std::function<void(std::string, std::string)>;public:    virtual ~BasicHttp(){};      void Init(uint32_t port);    bool Start();    bool Close();    bool RegisterHandler(std::string uri, handler f);    void UnRegisterHandler(std::string uri);    void Loop(int milli);    void SendReply(std::string uri, std::string reply);    void SendError(std::string uri, int errcode, std::string reply);protected:    using handler_map = std::map<std::string, handler>;    using connection_map = std::multimap<std::string, mg_connection*>;private:    static void EvHandler(struct mg_connection* nc, int ev, void* ev_data);    static void HandleRequst(struct mg_connection* nc, int ev, void *ev_data); public:    static handler_map _handlers;    static connection_map _connections;    char _port[11];    struct mg_mgr _mgr;};
// File:        basic_http.cpp// Description: ---// Notes:       ---// Author:      Haust <wyy123_2008@qq.com>// Revision:    2015-11-19 by Haust#include "basic_http.h"BasicHttp::handler_map BasicHttp::_handlers;BasicHttp::connection_map BasicHttp::_connections;void BasicHttp::Init(uint32_t port){    memset(_port, 0, sizeof(_port));    snprintf(_port, sizeof(_port), "%u", port);}bool BasicHttp::Start(){    mg_mgr_init(&_mgr, NULL);    auto nc = mg_bind(&_mgr, _port, EvHandler);    if(nullptr == nc)        return false;    mg_set_protocol_http_websocket(nc);    return true;}bool BasicHttp::Close(){    mg_mgr_free(&_mgr);    return true;}bool BasicHttp::RegisterHandler(std::string uri, handler f){    auto it = _handlers.find(uri);    if(_handlers.end() != it)        return false;    return _handlers.emplace(uri, f).second;}void BasicHttp::UnRegisterHandler(std::string uri){    auto it = _handlers.find(uri);    if(_handlers.end() != it)        _handlers.erase(it);}void BasicHttp::Loop(int milli){    mg_mgr_poll(&_mgr, milli);}void BasicHttp::EvHandler(struct mg_connection* nc, int ev, void* ev_data){   switch(ev){        case MG_EV_HTTP_REQUEST:            HandleRequst(nc, ev, ev_data);            break;       default:           break;   }}void BasicHttp::HandleRequst(struct mg_connection *nc, int ev, void* ev_data){    http_message* hm = (http_message*)ev_data;    std::string uri(hm->uri.p, hm->uri.len);    auto it = _handlers.find(uri);    if(_handlers.end() == it)        return;    _connections.emplace(uri, nc);    it->second(std::string(hm->query_string.p, hm->query_string.len),            std::string(hm->body.p, hm->body.len));}void BasicHttp::SendReply(std::string uri, std::string reply){    auto range = _connections.equal_range(uri);    if(range.first == range.second)        return;    auto it = range.first;    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",             (uint32_t)reply.length(), reply.c_str());    it->second->flags |= MG_F_SEND_AND_CLOSE;    _connections.erase(it);}void BasicHttp::SendError(std::string uri, int errcode, std::string reply){    auto range = _connections.equal_range(uri);    if(range.first == range.second)        return;    auto it = range.first;    mg_printf(it->second, "HTTP/1.1 %d %s\r\n", errcode, reply.c_str());    it->second->flags |= MG_F_SEND_AND_CLOSE;    _connections.erase(it);}#include "mongoose.c"

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.