mongoose实现httpserver,client
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongoose实现httpserver,client相关的知识,希望对你有一定的参考价值。
使用mongoose来做http协议的基础,基本上的函数都在一个c文件里面,直接包含c文件就可以实现一个httpserve和httpclient,可以实现一个小型的httpserver,要求的并发数不是很高,如下所示,直接将mongoose.c包含在项目里面。
1 server
首先http server 是一个线程类, 定义一个线程基类,然后httpserver从基类继承下去,使用start函数以后,线程开启,调用run函数,无限循环。server不仅是可以是httpserver,也可以是websocketserver。
/*
Author:钱波
email: 418511899@qq.com
wei: 18091589062
func :线程类
time: 2018年5月30日
*/
#ifndef _TTHREAD_RUN_ABLE_H_
#define _TTHREAD_RUN_ABLE_H_
#include <mutex>
#include <queue>
#include <thread>
#include <atomic>
#include <condition_variable>
#include <functional>
using namespace std;
class TThreadRunable
private:
//线程
thread _thread;
//等待信号
std::mutex _signal_mutex;
std::condition_variable _cond;
protected:
//char _running = false;
char _stop = true;
//锁定运行状态
std::mutex _mutex;
public:
TThreadRunable()
virtual ~TThreadRunable()
public:
char * status()
return &_stop;
void Join()
if (_thread.joinable())
_thread.join();
bool IsStop()
return _stop == 1 ? true : false;
void WaitForSignal()
std::unique_lock<std::mutex> ul(_signal_mutex);
_cond.wait(ul);
void Notify()
_cond.notify_one();
virtual int Start()
if (_stop == 1)//非運行中
_stop = 0;
_thread = std::thread(std::bind(&TThreadRunable::Run, this));
return 0;
return -1;
virtual void Stop()
_stop = 1; // true;
virtual void Run() = 0;
;
#endif
实现httpserver,主要是实现httpserver的run函数,实现循环。
#include "mongoose.h"
#include "TThreadRunable.h"
#include <string>
#include <functional>
#include <map>
using namespace std;
//typedef struct re_param
//
// void * pUser;
// string uri;
// string host;
// string uid;
// string message;
//re_param;
//using handler = std::function <void(re_param ¶m)>;
typedef struct request_param
//返回的
string retString;
map<string, string> params;
void insertParam(string key)
params[key] = "null";
void setParam(string key, string value)
params[key] = value;
const char* getParam(string key)
if (params.find(key) != params.end())
return params[key].c_str();
return NULL;
int getSize()
return (int)params.size();
map<string, string>::iterator iter;
const char * GetFirstParam()
iter = params.begin();
if (iter == params.end())
return NULL;
return iter->first.c_str();
void SetParamValue(const char *value)
if (iter != params.end())
iter->second = value;
const char * GetNextParam()
iter++;
if (iter == params.end())
return NULL;
else
return iter->first.c_str();
request_param;
using handler2 = std::function<void(request_param &rp)>;
typedef struct route_request
request_param _param;
handler2 func;
route_request;
class Service_HTTP :public TThreadRunable
protected:
using handler_map = std::map<std::string, route_request>;
handler_map _handlers;
public:
//handler handlestart = nullptr;
//handler handlestop = nullptr;
//handler hanlde_volume = nullptr;
//handler handle_microphone = nullptr;
handler_map &GetHandleMap()
return _handlers;
const char *s_http_port = "9091";
struct mg_serve_http_opts _s_http_server_opts;
struct mg_mgr _mgr;
struct mg_connection * _nc = NULL;
bool RegisterHandler(std::string uri, route_request f)
auto it = _handlers.find(uri);
if (_handlers.end() != it)
return false;
return _handlers.emplace(uri, f).second;
void UnRegisterHandler(std::string uri)
auto it = _handlers.find(uri);
if (_handlers.end() != it)
_handlers.erase(it);
public:
//static void handle_api(string uri, struct mg_connection *nc, struct http_message *hm);
static void handle_api2(string uri, struct mg_connection *nc, struct http_message *hm);
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data);
static int is_websocket(const struct mg_connection *nc)
return nc->flags & MG_F_IS_WEBSOCKET;
//广播该视频数据
void WebSocket_Broadcast(void * s2);
//void WebSocket_Broadcast1(void * pUser, uint8_t * data, int len);
public:
~Service_HTTP()
void Stop();
void Run();
;
下面是实现文件
#include "restful_server.h"
//#include "../CorePhone/TPictureInfo.h"
static struct mg_serve_http_opts s_http_server_opts;
void Service_HTTP::WebSocket_Broadcast(void *s)
//return ;
//int jpglen = 0;
//videosend2 *s2 = (videosend2 *)s;
//char * jpg = NULL;
//plus.EncodeRGB2Jpeg((char*)s2->data, s2->w, s2->h, (s2->w)*3, &jpg, jpglen);
//struct mg_connection *c;
//if (_nc != NULL)
// for (c = mg_next(_nc->mgr, NULL); c != NULL; c = mg_next(_nc->mgr, c))
// if (c == _nc) continue; /* Don't send to the sender. */
// mg_send_websocket_frame(c, WEBSOCKET_OP_BINARY, jpg, jpglen);
//
//
//if (jpg != NULL)
// delete[]jpg;
//void Service_HTTP::WebSocket_Broadcast1(void * pUser, uint8_t * data, int len)
//
// struct mg_connection *c;
// if (pUser == NULL)
// return;
//
// if (_nc != NULL)
// for (c = mg_next(_nc->mgr, NULL); c != NULL; c = mg_next(_nc->mgr, c))
// if (c == pUser)
// mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, data, len);
//
//
//
//
void Service_HTTP::handle_api2(string uri, struct mg_connection *nc, struct http_message *hm)
Service_HTTP *sh = (Service_HTTP*)nc->user_data;
if (sh == NULL)
return;
handler_map& hmap = sh->GetHandleMap();
handler_map::iterator iter;
iter = hmap.find(uri);
if (iter == hmap.end())
mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
return;
route_request & rr = iter->second;
const char * param = rr._param.GetFirstParam();
while (param != NULL)
char buffer[255];
mg_get_http_var(&hm->query_string, param, buffer, sizeof(buffer));
rr._param.SetParamValue(&buffer[0]);
//rr._param.setParam(string(param), string(buffer));
param = rr._param.GetNextParam();
/* Send headers */
//mg_printf(nc, "%s", "HTTP/1.1 200 OK\\r\\nTransfer-Encoding: chunked\\r\\n");
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
//允许哪些url可以跨域请求到本域
//mg_printf(nc, "Access-Control-Allow-Origin:*\\r\\n");
//允许的请求方法,一般是GET,POST,PUT,DELETE,OPTIONS
mg_printf(nc, "Access-Control-Allow-Methods:POST,OPTIONS,GET\\r\\n");
//允许哪些请求头可以跨域
mg_printf(nc, "Access-Control-Allow-Headers:x-requested-with,content-type\\r\\n");
if (rr.func != nullptr)
rr.func(rr._param);
string reply = "\\"ret\\":0";
if(!rr._param.retString.empty())
reply = rr._param.retString;
mg_printf(nc, "Content-Type:application/json\\r\\n");
mg_printf(nc, "Content-Length:%u\\r\\n\\r\\n%s\\r\\n", (uint32_t)reply.size(), reply.c_str());
//mg_printf(nc, "HTTP/1.1 200 OK\\r\\niConnection: close\\r\\nContent-Type: text/html\\r\\nContent-Length: %u\\r\\n\\r\\n%s\\r\\n",
nc->flags |= MG_F_SEND_AND_CLOSE;
//mg_send(nc, "", 0);
#if 0
void Service_HTTP::handle_api(string uri, struct mg_connection *nc, struct http_message *hm)
Service_HTTP *sh = (Service_HTTP*)nc->user_data;
if (sh == NULL)
return;
//const char * param = sh->_param.GetFirstParam();
if (uri.compare("/start") == 0)
char host[64];
char uid[64];
char message[64];
mg_get_http_var(&hm->query_string, "serverhost", host, sizeof(host));
mg_get_http_var(&hm->query_string, "uid", uid, sizeof(uid));
mg_get_http_var(&hm->query_string, "message", message, sizeof(message));
/* Send headers */
//mg_printf(nc, "%s", "HTTP/1.1 200 OK\\r\\nTransfer-Encoding: chunked\\r\\n");
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
//允许哪些url可以跨域请求到本域
mg_printf(nc, "Access-Control-Allow-Origin:*\\r\\n");
//允许的请求方法,一般是GET,POST,PUT,DELETE,OPTIONS
mg_printf(nc, "Access-Control-Allow-Methods:POST\\r\\n");
//允许哪些请求头可以跨域
mg_printf(nc, "Access-Control-Allow-Headers:x-requested-with,content-type\\r\\n");
string reply = "\\"result\\":0";
mg_printf(nc, "Content-Length:%u\\r\\n\\r\\n%s\\r\\n", (uint32_t)reply.size(), reply.c_str());
//mg_printf(nc, "HTTP/1.1 200 OK\\r\\niConnection: close\\r\\nContent-Type: text/html\\r\\nContent-Length: %u\\r\\n\\r\\n%s\\r\\n",
nc->flags |= MG_F_SEND_AND_CLOSE;
mg_send(nc, "", 0);
//mg_printf_http_chunk(nc, " \\"result\\": %ld ", 0);
//mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
re_param request;
request.uri = uri;
request.pUser = NULL;
request.host = host;
request.uid = uid;
request.message = message;
if (sh->handlestart != nullptr)
sh->handlestart(request);
//it->second(request);
OutputDebugString(L"start video to");
//callback(__void, host, uid, message);
else if (uri.compare("/stop") == 0) //停止
char message[64];
mg_get_http_var(&hm->query_string, "message", message, sizeof(message));
/* Send headers */
//mg_printf(nc, "%s", "HTTP/1.1 200 OK\\r\\nTransfer-Encoding: chunked\\r\\n");
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
//允许哪些url可以跨域请求到本域
mg_printf(nc, "Access-Control-Allow-Origin:*\\r\\n");
//允许的请求方法,一般是GET,POST,PUT,DELETE,OPTIONS
mg_printf(nc, "Access-Control-Allow-Methods:POST\\r\\n");
//允许哪些请求头可以跨域
mg_printf(nc, "Access-Control-Allow-Headers:x-requested-with,content-type\\r\\n");
string reply = "\\"result\\":0";
mg_printf(nc, "Content-Length:%u\\r\\n\\r\\n%s\\r\\n", (uint32_t)reply.size(), reply.c_str());
//mg_printf(nc, "HTTP/1.1 200 OK\\r\\niConnection: close\\r\\nContent-Type: text/html\\r\\nContent-Length: %u\\r\\n\\r\\n%s\\r\\n",
nc->flags |= MG_F_SEND_AND_CLOSE;
mg_send(nc, "", 0);
//mg_printf(nc, " \\"result\\": %ld ", 0);
//mg_send(nc, "", 0);
//mg_printf_http_chunk(nc, " \\"result\\": %ld ", 0);
//mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
//auto it = sh->GetHandleMap().find(uri);
//if (sh->GetHandleMap().end() == it)
// return;
re_param request;
request.uri = uri;
request.pUser = NULL;
request.message = message;
if(sh->handlestop!=nullptr)
sh->handlestop(request);
OutputDebugString(L"stop video");
//else if(uri.compare("getmicrophone"))
//获取
#endif
void Service_HTTP::ev_handler(struct mg_connection *nc, int ev, void *ev_data)
struct http_message *hm = (struct http_message *) ev_data;
//传送文件地址和转化的目的地址
// /api/t2pdf
switch (ev)
case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
printf("here connection\\n");
break;
case MG_EV_WEBSOCKET_FRAME:
struct websocket_message *wm = (struct websocket_message *) ev_data;
/* New websocket message. Tell everybody. */
struct mg_str d = (char *)wm->data, wm->size ;
//broadcast(nc, d);
break;
case MG_EV_HTTP_REQUEST:
string uri = string(hm->uri.p, hm->uri.len);
handle_api2(uri, nc, hm);
//if (mg_vcmp(&hm->uri, "/start") == 0)
// handle_api2(uri, nc, hm);
//
//else if (mg_vcmp(&hm->uri, "/stop") == 0)
// handle_api2(uri, nc, hm);
//
//else
//
// mg_serve_http(nc, hm, s_http_server_opts); /* Serve static content */
//
break;
case MG_EV_CLOSE:
if (is_websocket(nc))
OutputDebugString(L"websocket out");
break;
default:
break;
void Service_HTTP::Stop()
TThreadRunable::Stop();
Join();
void Service_HTTP::Run()
mg_mgr_init(&_mgr, NULL);
_nc = mg_bind(&_mgr, s_http_port, ev_handler);
_nc->user_data = this;
mg_set_protocol_http_websocket(_nc);
s_http_server_opts.document_root = "./public"; // Serve current directory
s_http_server_opts.enable_directory_listing = "yes";
//printf("Started on port %s\\n", s_http_port);
while (!IsStop())
mg_mgr_poll(&_mgr, 50);
mg_mgr_free(&_mg以上是关于mongoose实现httpserver,client的主要内容,如果未能解决你的问题,请参考以下文章