【智能音箱项目】-libvent库

1.事件和集合

      libvent的核心是个集合,把所有的需要监听的事件放在集合中,如果有满足条件的事件,就会触发回调函数去处理!

画个图,先搞清楚TCP的C/S架构

图中有三个文件描述符,sockfd和fd1、fd2

三个文件描述符可以分为两类:

socfd用于监听是否有客户端发起连接请求,fd1和fd2用于监听客户端是否向服务器发送数据。

每一个文件描述符可以理解成一个事件。事实上,libevent就是把文件描述符封装成了结构体bufferevent。把三个bufferevent同时放入集合中监听,就成了高并发服务器的雏形!

2.使用过程

(1)创建集合


struct event_base *event_base_new();

这行代码非常简单,创建一个空的集合。没有集合,libevent啥也不是。

用完之后,需要手动释放。


void event_base_free(struct event_base *);

(2)创建监听对象


struct evconnlistener *evconnlistener_new_bind(struct event_base *base,
     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
     const struct sockaddr *sa, int socklen);

/*智能音箱原始代码*/
PlayerServer::PlayerServer(const char *ip, int port)
{
	base = event_base_new();               //创建事件集合

	struct sockaddr_in server_addr;
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(port);
	server_addr.sin_addr.s_addr = inet_addr(ip);

	listener = evconnlistener_new_bind(base, listener_cb, base, 
		LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 10, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if (NULL == listener)
	{
		std::cout << "evconnlistener_new_bind error" << std::endl;
	}

	event_base_dispatch(base);      //监听集合
}

可以理解成,这一函数完成了socket、bind、listen、accept四个函数功能,并且把得到的sockfd(监听对象)添加到集合中。

参数的意义:

base:刚才创建的集合。

cb:回调函数。一旦有客户端连接服务器,就会触发该回调函数。

ptr:给回调函数传的参数。

flags:LEV_OPT_开头的宏定义,指定了监听对象的属性,比如释放监听对象的时候关闭socket连接、地址可以复用、多线程安全等等。

backlog:监听队列的大小。

sa:存放服务器的信息,用于绑定使用。

socklen:结构体的长度。

其中回调函数原型如下:


void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg)

/*智能音箱回调函数原始代码*/
void PlayerServer::listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg)
{
	struct event_base *base = (struct event_base *)arg;
	std::cout << "有客户端连接 " << fd << std::endl;

	//创建bufferevent事件
	struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
	if (NULL == bev)
	{
		std::cout << "bufferevent_socket_new error" << std::endl;
	}

	bufferevent_setcb(bev, read_cb, NULL, event_cb, base);
	bufferevent_enable(bev, EV_READ);
}

回调函数里面主要用于创建bufferevent对象,可以理解为一个bufferevent对应一个客户端。代码如下:

void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg)
{
    struct event_base *base = arg;
    
    struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    if (NULL == bev)
    {   
        printf("bufferevent_socket_new error!\n");
        exit(1);
    }   

    bufferevent_setcb(bev, read_cb, NULL, event_cb, NULL);
    bufferevent_enable(bev, EV_READ);
}

(3)开始监听

int event_base_dispatch(struct event_base *);

dispatch函数可以理解成一个循环,负责监听集合中的事件。如果没有这个函数,主函数会立即返回。

(4)设置回调函数

libevent里面用到的回调函数的地方特别多。

有客户连接请求,会触发回调函数;客户端发送数据会触发回调函数;客户端有异常时会触发回调函数。

对bufferevent事件设置回调函数需要用到两个函数:

//设置回调函数
void bufferevent_setcb(struct bufferevent *bufev, bufferevent_data_cb readcb, bufferevent_data_cb writecb, bufferevent_event_cb eventcb, void *cbarg);
//使能回调函数
int bufferevent_enable(struct bufferevent *bufev, short event);

其中,readcb最常使用,一旦有客户端发送数据,就会触发readcb回调函数。在智能音箱项目中,我们使用了两个回调函数,分别是服务器收到客户端消息时的回调函数readcb、客户端异常时回调函数event_cb;

(5)读取数据

libevent封装了两个函数分别用于读取和发送。

size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
wukongrobot 是一个简单、灵活、优雅的中文语音对话机器人/智能音箱项目,还可能是首个支持脑机交互的开源智能音箱项目。 特性: 1、模块化。 功能插件、语音识别、语音合成、对话机器人都做到了高度模块化,第三方插件单独维护,方便继承和开发自己的插件。 2、中文支持。 集成百度、科大讯飞、阿里、腾讯等多家中文语音识别和语音合成技术,且可以继续扩展。 3、对话机器人支持。 支持基于 AnyQ 的本地对话机器人,并支持接入图灵机器人、Emotibot 等在线对话机器人。 4、全局监听,离线唤醒。 支持 Muse 脑机唤醒,及无接触的离线语音指令唤醒。 5、灵活可配置。 支持定制机器人名字,支持选择语音识别和合成的插件。 6、智能家居。 支持和 mqtt、HomeAssistant 等智能家居协议联动,支持语音控制智能家电。 7、后台配套支持。 提供配套后台,可实现远程操控、修改配置和日志查看等功能。 8、开放API。 可利用后端开放的API,实现更丰富的功能。 9、安装简单,支持更多平台。 相比 dingdang-robot ,舍弃了 PocketSphinx 的离线唤醒方案,安装变得更加简单,代码量更少,更易于维护并且能在 Mac 以及更多 Linux 系统中运行。 环境要求: Python 版本 wukong-robot 只支持 Python 3.5+,不支持 Python 2.x 。 设备要求 wukong-robot 支持运行在以下的设备和系统中: 64bit Mac OS X 64bit Ubuntu(12.04 and 14.04) 全系列的树莓派(Raspbian 系统) Pine 64 with Debian Jessie 8.5(3.10.102) Intel Edison with Ubilinux (Debian Wheezy 7.8) 装有 WSL(Windows Subsystem for Linux) 的 Windows

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值