bufferevent监听事件的原理可以归纳如下:
基本结构:
bufferevent是libevent库中的一个组件,它用于简化在已连接套接字上接收和发送数据的过程。
bufferevent内部包含两个主要的缓冲区:读缓冲区和写缓冲区,这两个缓冲区通过队列实现,遵循先进先出的原则。
读事件监听:
当读缓冲区中有数据时,bufferevent会触发用户所设置的读回调函数。
在这个回调函数中,用户可以通过调用bufferevent_read()来读取数据。bufferevent_read()函数在这里替代了传统的read函数,用于从读缓冲区中读取数据。
写事件监听:
当用户想要向写缓冲区中写入数据时,会调用bufferevent_write()函数。
bufferevent_write()将数据添加到写缓冲区中,如果底层传输端口(如套接字)已经准备好发送数据(即写缓冲区中的数据可以被发送),则会自动将数据发送出去。
如果数据发送成功,bufferevent会触发用户所设置的写回调函数来通知发送已完成。
事件监听流程:
bufferevent通过监听底层传输端口(如套接字)的可读和可写事件来实现数据的接收和发送。
当底层传输端口可读时,bufferevent会读取数据到读缓冲区,并触发读回调函数。
当底层传输端口可写时,bufferevent会检查写缓冲区中是否有待发送的数据,如果有则自动发送,并触发写回调函数。
设置回调:
由于bufferevent有两个缓冲区,所以需要分别设置读和写的回调函数。
另外,还可以设置一个事件回调函数,用于处理一些特殊的事件,如错误发生、连接断开等。
回调函数的设置可以通过调用bufferevent_setcb()函数来完成。
bufferevent结构体:
bufferevent结构体中包含了两个event成员,分别用于监听底层传输端口的可读和可写事件。
结构体中还包含了两个evbuffer成员,分别对应读缓冲区和写缓冲区。
综上所述,bufferevent通过内部的读缓冲区和写缓冲区,以及设置相应的回调函数,实现了对底层传输端口(如套接字)的可读和可写事件的监听,从而简化了在已连接套接字上接收和发送数据的过程。
总结
两个缓存区是指
读缓存区
客户端通过socket发过来的数据不是直接发给服务端的应用层的,这期间会经过好几个路口:
- 第一个是socket的读缓存区,客户端发来的数据会存到这里;
- 第二个是bufferevent的读缓存区,将socket读缓存区的数据读到bufferevent的读缓存区(只有设置读使能才会(bufferevent_enable(bev,
EV_READ))); - 第三个是应用层通过读回调函数读取bufferevent的读缓存区数据;
写缓存区
服务端应用层的数据也不是直接写给客户端的应用层的:
- 第一个是通过写回调函数写到bufferevent的写缓存区;
- 第二个是bufferevent的写缓存区将这部分数据写给socket的写缓存区(bufferevent设置写使能时(bufferevent_enable(bev, EV_WRITE)));
三个回调:读、写、事件回调(出错、断开等)
void bufferevent_setcb(struct bufferevent *bufev, bufferevent_data_cb readcb, bufferevent_data_cb writecb,bufferevent_event_cb eventcb, void *cbarg);
分别对应 bufferevent_setcb 函数里面的readcb、writecb、eventcb;
读写使能
- 读使能:要不要将socket读缓存区的数据读到bufferevent读缓存区;
- 写使能:要不要将bufferevent写缓存区的数据写给socket写缓存区;
注意两个缓冲区、读写回调、读写使能的关系!!!
(针对于服务器连接的epoll、libevent、bufferevent;什么IO多路复用、线程池之类;还需要一定的时间把他们连起来,概念和实践杂糅起来就很懵~~)