mongoose框架示例代码解析(一)
参考:
前言:
OK,感谢完恩公,来看看今天的正文吧~对了,把昨天写时隔九年重新遇到半个初恋的博客置顶一下,时刻给自己一些刺激。这里也放个链接,没错,皮这一下我很快乐!初步了解mac下C源码的编译过程_qq_31433709的博客-CSDN博客
不得不说,起名字真的是一门学问,这两个源文件的方法名还有参数名称都堪称完美一目了然!
说起来,我vim上的C环境都还没有弄呢,这撸代码的过程感觉真的不够快乐!晚上顺便搞定吧!如果没有找到(虽然这个相当不现实),那就顺便学学怎么编写插件吧= =!
正文
一. 服务器端:
源码文件:simplest_web_server.c
// Copyright (c) 2015 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
static const char *s_http_port = "8000";
static struct mg_serve_http_opts s_http_server_opts;
static void ev_handler(struct mg_connection *nc, int ev, void *p) {
if (ev == MG_EV_HTTP_REQUEST) {
mg_serve_http(nc, (struct http_message *) p, s_http_server_opts);
}
}
int main(void) {
struct mg_mgr mgr;
struct mg_connection *nc;
mg_mgr_init(&mgr, NULL);
printf("Starting web server on port %s\n", s_http_port);
nc = mg_bind(&mgr, s_http_port, ev_handler);
if (nc == NULL) {
printf("Failed to create listener\n");
return 1;
}
// Set up HTTP server parameters
mg_set_protocol_http_websocket(nc);
s_http_server_opts.document_root = "."; // Serve current directory
s_http_server_opts.enable_directory_listing = "yes";
for (;;) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
(1)先初步扫一眼:
呜呜,好多已经被封进框架的方法调用,常量和结构体:
- 结构体:
- mg_mgr
- mg_connection
- mg_serve_http_opts
- 方法调用:
- mg_mgr_init
- mg_bind
- mg_serve_http
- mg_set_protocol_http_websocket
- mg_mgr_pool
- mg_mgr_free
- 常量:
- MG_EV_HTTP_REQUEST
只导入了一个头文件,去这里面找找呗= =,哇,6277行,ok,小朋友,你是不是有很多疑问?
头文件中能获取到的我感觉最多只有常量,而方法的实现和结构体的定义,我还是感觉要从.c文件中去获取。
(2)那就先看看头文件吧
vim全局搜一下,MG_EV_HTTP_REQUEST的结果,找到定义就行了,其余的嘛,本来想也列出来,不过为了篇幅的简约,还是省略比较好,个人感觉(大概瞄了一下~),然后我发现无论是结构体还是方法调用抑或是常量,在头文件里面都有很具体的讲解,甚至有示例代码,所以建议直接在mongoose.h文件中自行搜索,然后对于mg_mgr_pool的1000参数,还是需要看.c文件中的具体实现
然后这是我大体理了一圈的结果,毕竟是第一次写这方面的内容,差是差了点,不过毕竟是为了自我的提升(自我安慰),总有从差到好的过程嘛!
// Copyright (c) 2015 Cesanta Software Limited
// All rights reserved
//导入mongoose所依赖的必须头文件
#include "mongoose.h"
//指定默认的服务器http端口号
static const char *s_http_port = "8000";
//指定http链接的各种选项
static struct mg_serve_http_opts s_http_server_opts;
//ev_handler指定的event handler,即事件处理,mg指代的是mongoose
static void ev_handler(struct mg_connection *nc, int ev, void *p) {
if (ev == MG_EV_HTTP_REQUEST) {
mg_serve_http(nc, (struct http_message *) p, s_http_server_opts);
}
}
//总入口,一切的开始
int main(void) {
struct mg_mgr mgr;
struct mg_connection *nc;
//初始化mg_mar变量
mg_mgr_init(&mgr, NULL);
printf("Starting web server on port %s\n", s_http_port);
//这里有点函数式的感觉,传入的不是对象,而是方法指针
//将mgr和其中的mgr_connection以及对应的端口号还有对应的不同event的处理器所绑定,并返回对应的绑定后的mg_connection对象
nc = mg_bind(&mgr, s_http_port, ev_handler);
if (nc == NULL) {
printf("Failed to create listener\n");
return 1;
}
// Set up HTTP server parameters
mg_set_protocol_http_websocket(nc);
//设置客户端访问服务器的初始路径,这里设置为"."即为可执行文件的当前路径
s_http_server_opts.document_root = "."; // Serve current directory
//同时设置是否支持显示当前目录下的文件信息
s_http_server_opts.enable_directory_listing = "yes";
for (;;) {
//这里的1000是什么意思呢?
//翻译一下文档中对这个方法的描述:
//这个方法执行实际上的IO操作并且必须在一个循环中被调用(一个事件循环)。
//它返回了生成的用户事件数目(除了POLL)。
//第二个参数是以毫秒为单位的睡眠最大时间。
//该方法为IO操作检查了所有的连接(connection)。如果至少有一个连接已经准备好IO操作,此方法将切换到对应的事件处理器然后返回。
mg_mgr_poll(&mgr, 1000);
//所以说,1000到底是什么意思?看来光看头文件比较难啊。
//ok,大概看了看实现,1000是设置的请求超时时间
}
//解构mg_mgr,该方法中应该同时解构了mg_connection,并释放了对应占用的内存,道理的确是这样,但是什么情况下会跳出这个死循环呢?如果我直接通过信号,貌似不会走这步,并没有看见输出stopped的信息
mg_mgr_free(&mgr);
printf("stopped mongoose server");
return 0;
}
小结:
OK,感觉今天看到这个程序差不多了,也适当看到了一些细节,服务端的流程也基本理了一圈了。早睡早起身体好~