Mongoose web服务器多线程操作

文章介绍了如何在mongoose7.9版本上实现多线程服务,强调了从6.7版本后官方不再提供多线程接口。通过mg_mkpipe创建socket管道来处理HTTP请求,文中提出了在mg_connection结构体中增加标识来复用连接,避免每次请求都创建新的连接,从而优化资源使用。工作者线程处理完成后直接通过内存中的mg_iobuf结构体发送结果,而不是直接使用send函数,以防止错误。

mongoose用于轻量级web服务使用,只要导入mongoose.c和mongoose.h即可,非常方便。
从6.7版本后,官方版本不再提供多线程接口,多线程服务需要自己实现。
本文以7.9版本为基础,实现多线程服务。

mongoose简介

mongoose下载地址: https://github.com/cesanta/mongoose

mg_mgr: mongoose的管理器。
mg_connection: mongoose的连接,每个连接创建一个对象。
mg_mkpipe: 创建一个socket管道,并返回一个socket,用于工作者线程返回数据

mongoose实现多线程的方式

当一个连接请求(MG_EV_HTTP_MSG)被接收到后,使用mg_mkpipe创建一个socket管道对,并将新建的connection和请求连接的connection连接起来,将socket管道对得到的socket句柄发送给工作者线程。工作者线程处理完成后将数据写入socket,然后通过两个连接间的关系,将数据返回给客户端。如下图所示:
在这里插入图片描述
但是,mongoose自带的examples中,每个请求都要调用一次mg_mkpipe,生成一个连接,而且mg_mkpipe使用的是udp协议生成,udp协议关闭时,对方是无法得知的,造成新生成的连接会被浪费掉。
所以要对这块进行改造。
1、在mg_connection结构体中增加一个socket标识(fd_woker),用来作为工作者线程的参数,并在结构体书初始化(mg_alloc_conn)的时候赋值为0,结构体销毁(mg_close_conn)的时候关闭连接。
2、在接收到http请求(MG_EV_HTTP_MSG)时,先判断当前连接有没有对应的fd_woker,如果有就直接使用它,如果没有时再使用mg_mkpipe新建。

	struct userdata *data = (userdata *)calloc(1, sizeof(*data));  // worker will free it
	// parse headers or use request body, duplicate data and pass it to worker thread
	data->body = mg_strdup(hm->body);              // worker will free it
	data->sock = c->fd_worker ? c->fd_worker : (c->fd_worker = mg_mkpipe(c->mgr, pcb, c, true));
	_beginthread(woker_thread_function, 0, data);		   // Start thread and pass data

3、工作者线程处理完后,不要关闭socket连接,等http连接断开后,都会自动关闭
4、工作者线程回复处理结果时,不要直接向socket发送结果数据(直接send大数据会发送错误),直接发送一个mg_iobuf结构体就好,因为是同一个进程,可以直接从内存中读取数据。

//工作者线程发送
	mg_iobuf buf = { 0, 0, 0, 0 };
	mg_iobuf_add(&buf, buf.buf.len, ret_msg.c_str(), ret_msg.length());
	int e = send(p->sock, (const char *)&buf, sizeof(struct mg_iobuf), 0);
//socket管道线程接收
case MG_EV_READ:
	mg_iobuf buf = { 0, 0, 0, 0 };
	if (c->recv.len == sizeof(struct mg_iobuf)) {
		memcpy(&buf, c->recv.buf, sizeof(struct mg_iobuf));
		mg_http_reply(parent, 200, "", "%.*s\n", buf.size,  buf.buf);  // Respond!
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值