嘛....

注意:这里是使用mongoose实现HTTP服务,非数据库使用。

最近由于需要使用HTTP服务端,原先是使用的Qt框架实现的HTTP服务端,然后发现有些缺陷导致我不得不放弃这个框架,也不是完全放弃,只是HTTP服务端这里不再使用Qt,用Qt做高并发真的有点不好。

然后毅然的选择了mongoose这个框架,主要是听说这玩意 嵌入到代码中非常方便。下载之后发现果然就一个 h文件和cpp文件。。

于是开始研究这个框架,根据mongoose 用户手册再加上一堆实例教程,基本上写了一个类 进行操作封装(并不是完全的封装了)

MoHttp.h文件
主要是实现mongoose框架的基本 变量获取。注意里面有重载,主要是为了方便使用。
#define _MOHTTP_H
#ifdef _MOHTTP_H #include "mongoose.h"
#include <iostream> using namespace std; const int CHAR_HTTP_VAR_MAX = ;
const int CHAR_HTTP_COOKIE_MAX = ; class MoHttp
{
private:
struct http_message *hm = NULL; public:
MoHttp(struct http_message *);
~MoHttp();
int getGetVar(const char*, char*) const; //获取变量
void getGetVar(const char*, string &) const; //获取变量
int getPostVar(const char*, char*) const; //获取变量
void getPostVar(const char*, string &) const; //获取变量
int getCookie(const char*, char*) const; //获取Cookie
void getCookie(const char*, string &) const; //获取Cookie
int Model() const; //判断当前模式 POST/GET 1为 GET 否则为0
}; #endif
MoHttp.cpp
实现各类方法。
#include "MoHttp.h"

MoHttp::MoHttp(struct http_message * hm = NULL)
{
this->hm = hm;
} int MoHttp::getGetVar(const char* name, char* var) const
{
memset(var, '\0', sizeof(var));
if (hm == NULL || name == NULL || hm->query_string.p == NULL)return -;
return mg_get_http_var(&hm->query_string, name, var, sizeof(var)); //获取变量
} void MoHttp::getGetVar(const char* name, string & str) const
{
str = "";
char var[CHAR_HTTP_VAR_MAX];
var[] = '\0';
if (hm == NULL || name == NULL || hm->query_string.p == NULL)return;
mg_get_http_var(&hm->query_string, name, var, sizeof(var)); //获取变量
if (var[] == '\0'){
return;
}
str = var; //如果数据正确
} int MoHttp::getPostVar(const char* name, char* var) const
{
memset(var,'\0',sizeof(var));
if (hm == NULL || name == NULL || hm->body.p == NULL)return -;
return mg_get_http_var(&hm->body, name, var, sizeof(var)); //获取变量
} void MoHttp::getPostVar(const char* name, string & str) const
{
str = "";
char var[CHAR_HTTP_VAR_MAX];
var[] = '\0';
if (hm == NULL || name == NULL || hm->query_string.p == NULL)return;
mg_get_http_var(&hm->body, name, var, sizeof(var)); //获取变量
if (var[] == '\0'){
return;
}
str = var; //如果数据正确
} int MoHttp::Model() const
{ if (hm == NULL || hm->method.p == NULL)return -; //数据错误
if (mg_vcmp(&hm->method, "POST") != )return ;
return ; }
int MoHttp::getCookie(const char * name, char * var) const
{
memset(var, '\0', sizeof(var));
//mg_printf(nc, "Set-Cookie: %s=%s; path=/\r\n", "wwe", "123456789"); 发送Cookie
if (hm == NULL) return -;
struct mg_str *cookie_header = mg_get_http_header(hm, "cookie"); //获取Cookie 整条
if (cookie_header == NULL) return -; //<0
return mg_http_parse_header(cookie_header, name, var, sizeof(var));
} void MoHttp::getCookie(const char* name, string & str) const
{
str = "";
char var[CHAR_HTTP_COOKIE_MAX]; //Cookie 最大更长
var[] = '\0';
if (hm == NULL || name == NULL || hm->query_string.p == NULL)return;
struct mg_str *cookie_header = mg_get_http_header(hm, "cookie"); //获取Cookie 整条
if (cookie_header == NULL) return;
mg_http_parse_header(cookie_header, name, var, sizeof(var));
if (var[] == '\0'){
return;
}
str = var; //如果数据正确
} MoHttp::~MoHttp()
{ }

使用方法:

Mo.cpp(或Main.cpp)

// Copyright (c) 2016 by Suwings
// All rights reserved #include <iostream>
#include "MoHttp.h" using namespace std; static char *s_http_port = "";
static struct mg_serve_http_opts s_http_server_opts; MoHttp * mo = NULL; static void ev_handler(struct mg_connection *nc, int ev, void *p) {
if (ev == MG_EV_HTTP_REQUEST) { //如果是HTTP 请求
struct http_message *hm = (struct http_message *) p; //传为
mo = new MoHttp(hm); //记得释放内存,实例化 MoHttp
if (mo->Model()==){
//GET
string w;                            //测试代码    
mo->getGetVar("user",w);                   //测试代码
if (w != "")cout << "变量:" << w.c_str() << endl;     //测试代码 }else{                              //测试代码
//POST
}                                 //测试代码
delete mo; //释放变量
mg_serve_http(nc, hm, s_http_server_opts); //数据发送
}
} int main(void) {
struct mg_mgr mgr;
struct mg_connection *nc;
//struct mg_request_info *ww;
mg_mgr_init(&mgr, NULL);
printf("[状态] 服务器已经开启在端口: %s\n", s_http_port); nc = mg_bind(&mgr, s_http_port, ev_handler);
if (nc == NULL) {
printf("Failed to create listener\n");
return ;
} // Set up HTTP server parameters
mg_set_protocol_http_websocket(nc);
s_http_server_opts.document_root = "./www/"; // Serve current directory
s_http_server_opts.enable_directory_listing = "no"; //Set if show dir
for (;;) {
mg_mgr_poll(&mgr, );
}
mg_mgr_free(&mgr); return ;
}

看了几个小时之后,差不多只能写出这么点东西了。然后我就一直在想。

但是你有没有发现,如果浏览器要是发送 Ajax 数据过来,假定逻辑在 C++ 代码里面,我应该如何设置返回的数据啊?

的确,这个类也没有加入 返回的数据,这个问题我也一直在困扰。

难道mongoose 框架都没有函数是可以设置数据在 body 的?百思不得其解的我于是去找了一下 mongoose 文档里面的例子,发现了一个Cookie验证的例子,原本我以为不管怎么样也会有设置数据的地方了,但是我惊奇的发现,是这样的:

Cookie_auth.c 例子文件

static void set_session_cookie(struct mg_connection *nc,    
const struct session *s) {
mg_printf(nc, "Set-Cookie: %s=%" INT64_X_FMT "; path=/\r\n",
SESSION_COOKIE_NAME, s->id);
} /*
* If requested via GET, serves the login page.
* If requested via POST (form submission), checks password and logs user in.
*/
static void login_handler(struct mg_connection *nc, int ev, void *p) {    //主要看这个函数
struct http_message *hm = (struct http_message *) p;
if (mg_vcmp(&hm->method, "POST") != ) {
/* Serve login.html */
mg_serve_http(nc, (struct http_message *) p, s_http_server_opts);
} else {
/* Perform password check. */
char user[], pass[];
int ul = mg_get_http_var(&hm->body, "user", user, sizeof(user));
int pl = mg_get_http_var(&hm->body, "pass", pass, sizeof(pass));
if (ul > && pl > ) { //如果有数据
if (check_pass(user, pass)) { //验证账号和密码 函数无须理会
struct session *s = create_session(user, hm); //mg_printf 是直接输出数据,并不是输出到body
mg_printf(nc, "HTTP/1.0 302 Found\r\n");
set_session_cookie(nc, s); //他是进行了一次跳转,并且直接返回的HTTP头
mg_printf(nc, "Location: /\r\n");
mg_printf(nc, "\r\nHello, %s!\r\n", s->user);
//这句是控制台输出
fprintf(stderr, "%s logged in, sid %" INT64_X_FMT "\n", s->user, s->id);
} else {
mg_printf(nc, "HTTP/1.0 403 Unauthorized\r\n\r\nWrong password.\r\n");
}
} else {
mg_printf(nc, "HTTP/1.0 400 Bad Request\r\n\r\nuser, pass required.\r\n");
}
nc->flags |= MG_F_SEND_AND_CLOSE;
}
(void) ev;
}

看完了之后我就跟纳闷了,为什么要直接输出HTTP头?框架难道真的没有提供类似的方法吗?

然后尝试了各类函数:

也无果,这些函数会 输出到 HTTP 响应头之前。

所以,是不是这个框架真的没有 什么设置返回的body 的函数呢?

总之目前只学到这里,也许有什么地方确实没有了解。暂且先记录下来,等知道了之后再续写。

Mongoose 利用实现HTTP服务的更多相关文章

  1. Java进阶(五十二)利用LOG4J生成服务日志

    Java进阶(五十二)利用LOG4J生成服务日志 前言 由于论文写作需求,需要进行流程挖掘.前提是需要有真实的事件日志数据.真实的事件日志数据可以用来发现.监控和提升业务流程. 为了获得真实的事件日志 ...

  2. [android] 代码注册广播接收者&利用广播调用服务的方法

    利用广播调用服务里面的方法,间接的方式调用服务内部的方法,与现实中差不多,请媒体曝光 主界面里面 在界面创建的时候开启一下服务普通的startService()方法 发送一条广播出去 获取Intent ...

  3. 小程序 青少儿书画 利用engineercms作为服务端

    因为很多妈咪们喜欢发布自己宝宝的作品,享受哪些美好时刻,记录亲子创作过程. 为了方便妈咪们展示亲子创作,比如宝宝们画作,涂鸦,书法,作文,其他才艺,特利用engineercms作为服务端,重新设计了一 ...

  4. spring cloud(服务消费者(利用ribbon实现服务消费及负载均衡)——初学二)

    Ribbon是一个基于HTTP和TCP客户端的负载均衡器,利用ribbon实现服务消费,并实现客户端的负载均衡. 一.准备工作(利用上一节的内容) 启动服务注册中心 启动computer-servic ...

  5. Spring Cloud实战之初级入门(四)— 利用Hystrix实现服务熔断与服务监控

    目录 1.环境介绍 2.服务监控 2.1 加入依赖 2.2 修改配置文件 2.3 修改启动文件 2.4 监控服务 2.5 小结 3. 利用hystrix实现消费服务熔断 3.1 加入服务熔断 3.2 ...

  6. 使用接口的方式调用远程服务 ------ 利用动态调用服务,实现.net下类似Dubbo的玩法。

    分布式微服务现在成为了很多公司架构首先项,据我了解,很多java公司架构都是 Maven+Dubbo+Zookeeper基础上扩展的. Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按 ...

  7. spring cloud(服务消费者(利用feign实现服务消费及负载均衡)——初学三)

    Feign是一个声明式的Web Service客户端,我们只需要使用Feign来创建一个接口并用注解来配置它既可完成. 它具备可插拔的注解支持,包括Feign注解和JAX-RS注解.Feign也支持可 ...

  8. SpringAOP01 利用AOP实现权限验证、利用权限验证服务实现权限验证

    1 编程范式 1.1 面向过程 1.2 面向对象 1.3 面向切面编程 1.4 函数式编程 1.5 事件驱动编程 2 什么是面向切面编程 2.1 是一种编程范式,而不是一种编程语言 2.2 解决一些特 ...

  9. 高可用服务之Keepalived利用脚本实现服务的可用性检测

    上一篇博客主要聊到了keepalived高可用LVS集群的相关配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13659428.html:keepalive ...

随机推荐

  1. 第4章 scrapy爬取知名技术文章网站(1)

    4-1 scrapy安装以及目录结构介绍 安装scrapy可以看我另外一篇博文:Scrapy的安装--------Windows.linux.mac等操作平台,现在是在虚拟环境中安装可能有不同. 1. ...

  2. Java jxl导入excel文件,导入的数字、身份证号码、手机号变成了科学计数法,解决方案

    原文出自:https://blog.csdn.net/seesun2012 这是一个execl文件导入数据库操作,使用jxl解析execl导入数据库过程出现了科学计数法,与想要导入的数据不匹配,以下是 ...

  3. SQL Serever学习5——数据库配置

    数据库的主要属性 限制访问 用来设置数据允许用户访问的状态,或者说允许多少客户访问,有3个选项: MULTI_USER(多个),大多数数据库正常状态,允许多个用户同时访问该数据库. SINGLE_US ...

  4. [javaSE] 多线程(join方法)

    多条线程并发执行,随机切换,调用join()方法,会使当前线程所在的线程(一般主线程)冻结,直到当前线程结束,所在的线程才恢复继续执行 class JoinTestDemo implements Ru ...

  5. [javaSE] 进制转换(二进制十进制十六进制八进制)

    十进制转二进制,除2运算 十进制6转二进制是 110  (注意从右往左写,使用算式从下往上写) 二进制转十进制,乘2过程 二进制110转十进制  0*2的0次方+1*2的1次方+1*2的2次方=6 对 ...

  6. 四、闭锁之CountDownLatch

    一.简介 闭锁是Java的一种同步工具类.我们在程序运行过程中,某个任务需要等待其它一个到多个的任务全部完成才会执行,这个等待的期间就叫做闭锁. CountDownLatch是闭锁的一种实现,它支持一 ...

  7. Java编程基础知识总结大全(Ⅱ)

    7.类型转换 精度从高到低 double float long int short(char) byte (1)自动类型转换 将一个低精度---高精度 (2)强制类型转换 将一个高精度---低精度 ...

  8. linux下配置环境变量方式

    linux下配置环境变量有多种方式,下面简述之 方式1.编辑 /etc/profile 文件,增加如下内容 JAVA_HOME=/usr/local/jdk1. export JAVA_HOME PA ...

  9. Linux下ipv6配置系列

    Linux下ipv6配置系列一:如何配置Linux系统ipv6环境 Linux下ipv6配置系列二:如何为Nginx添加ipv6模块 Linux下ipv6配置系列三:如何为Nginx配置IPv6端口监 ...

  10. CF235C Cyclical Quest

    题意 给定一个长度为\(n\)的母串 \(q\)组询问 这个串可以旋转(就是把最后一位丢到最前面这样子) 问这个串以及其旋转的串在给定的串中出现了多少次 Sol 旋转就把它复制一遍接在后面 然后就在\ ...