使用mongoose库搭建http服务器
1.
定义操作句柄,
struct mg_mgr{}mgr;
2.初始化句柄,
void mg_mgr_init(struct mg_mgr *);
3.创建http的监听连接,就是创建一个socket,定义为http协议通信,对于请求的数据就会进行http协议格式解析
struct mg_connection *mg_http_listen
(struct mg_mgr *,
const char *url,
mg_event_handler_t fn,
void *fn_data);
struct mg_mgr *//操作句柄
const char *url//监听地址,"0.0.0.0:9000"
mg_event_handler_t fn//回调函数,当收到请求,解析完毕后就会调用这个函数进行业务处理
void *fn_data//传递给回调函数的数据
//返回值,成功返回创建的连接,失败返回NULL
回调函数
static void fn(
struct mg_connection *c,
int ev,
void *ev_data,
void *fn_data)
struct mg_connection *c//当前发送本次请求的连接
int ev//本次请求所触发的事件
void *ev_data//如果是http请求则是mg_http_message数据,如果是websocket消息则是mg_ws_message数据
void *fn_data//传递给回调函数的数据
触发事件类型
MG_EV_HTTP_MSG,http请求到来事件
MG_EV_WS_OPEN,websocket建立连接完成事件
MG_EV_WS_MSG,websocket消息到来事件
MG_EV_CLOSE,连接断开事件
4.
开始轮询监听,等待所有连接,有数据到来进行处理
void mg_mgr_poll(struct mg_mgr *mgr, int ms);
int ms//超时等待时间
使用mongoose库搭建http服务器的流程
1.创建句柄,
初始化句柄
2.创建监听链接,设置http标志位,设置事件处理回调函数
3.开始监听,有新连接请求到来,则创建新连接,设置标志位为http服务器标志位,表示这是一个http连接
4.开始轮询判断哪个连接有数据到来,使用多路转接select模型实现轮询判断
5.有数据到来了,如果当前连接是http服务器连接,则按照http协议格式解析请求,然后调用回调函数
6.在回调函数中进行具体的业务处理,
在回调函数中,根据ev_data里的各项请求信息,确定是一个什么请求,然后再进行具体的业务处理
websocket,服务器收到浏览器客户端的升级协议请求之后,进行回复确认,然后将连接的标志位设置为websocket标志位,表示是一个websocket连接,当这个连接收到请求后,就会按照websocket协议格式解析数据,然后调用回调函数进行业务处理
example-http.cpp
#include <iostream>
#include <string>
#include "mongoose.h"
using namespace std;
//回调函数
//c-当前的连接,ev-事件,ev_data-处理完毕的数据,fn_data-传入的数据
void callback(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
{
switch (ev)
{
//表示当前请求是一个http协议请求
case MG_EV_HTTP_MSG:
{
//hm在整个switch语句里生效,case后加一个{},限定作用域
struct mg_http_message *hm = (struct mg_http_message *)ev_data;
//在终端打印请求信息
string method;
method.assign(hm->method.ptr, hm->method.len);
cout << method << endl;
string uri;
uri.assign(hm->uri.ptr, hm->uri.len);
cout << uri << endl;
//匹配本次的请求是否为指定的uri请求
if (mg_http_match_uri(hm, "/hello"))
{
//不区分请求方法
string body = "<html><body><h1>Hello World!</h1></body></html>";
string header = "Content-Type:text/html\r\n";
//自己组织简单响应
mg_http_reply(c, 200, header.c_str(), "%s", body.c_str());
}
else if (mg_http_match_uri(hm, "/websocket"))
{
//当前连接一旦升级websocket协议,则下次有数据到来时触发的就是WS_MSG事件
//确认升级websocket协议
mg_ws_upgrade(c, hm, NULL);
}
else
{
//请求的相对根目录
struct mg_http_serve_opts opts = {.root_dir = "./web_root"};
//静态页面资源响应
mg_http_serve_dir(c, hm, &opts);
}
}
break;
//表示当前请求是一个websocket协议请求
case MG_EV_WS_MSG:
//struct mg_ws_message *wm=(struct mg_ws_message*)ev_data;
break;
//表示当前连接断开
case MG_EV_CLOSE:
break;
default:
break;
}
return;
}
int main()
{
//定义句柄
struct mg_mgr mgr;
//初始化句柄
mg_mgr_init(&mgr);
//创建http连接
struct mg_connection *lst_http;
//mg_http_listen(句柄,监听地址,回调函数,传入参数)
lst_http = mg_http_listen(&mgr, "0.0.0.0:9000", callback, NULL);
if (lst_http == NULL)
{
return -1;
}
//开始轮询监听
//while(1)设置死循环,超时后,也继续进行监听
while (1)
{
//1000ms监听不到连接就结束
mg_mgr_poll(&mgr, 1000);
}
return 0;
}
g++ -std=c++11 http.cpp mongoose.c -o http
./http