Los fundamentos de libevent(12) bufferevent

1. El concepto básico de bufferevent

bufferevent es una E/S de búfer de eventos en libevent, que implementa operaciones básicas de recepción/envío de socket internamente. Los usuarios solo necesitan llamar a la API de bufferevent para leer y escribir datos.

(1) Búfer: cada evento de búfer tiene un búfer de lectura (entrada) y un búfer de escritura (salida).La estructura de datos es evbuffer, que es un búfer de datos para almacenar en búfer los datos enviados o recibidos en la red.

(2) devolución de llamada:

// 读取和写入回调
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);

// 事件回调,其中what表示发生的事件,具体后面有说明
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short what, void *ctx);

(3) Nivel de agua: la llamada de la función de devolución de llamada se puede ajustar configurando el nivel de agua.

(3.1) Lea el nivel de agua bajo: cuando el volumen de datos del búfer de entrada alcance o supere este nivel de agua, se llamará a la función de devolución de llamada, es decir, si el volumen de datos no cumple con el requisito de nivel de agua, la devolución de llamada no será ser llamado;

(3.2) Leer nivel alto de agua: cuando el volumen de datos del búfer de entrada alcanza este nivel de agua, bufferevent dejará de leer hasta que se lean los datos en el búfer de entrada, haciendo que el volumen de datos sea inferior a este nivel de agua. Nota utilizada para limitar la cantidad máxima de datos leídos a la vez.

(3.3) Escriba bajo nivel de agua: cuando la cantidad de datos en el búfer de salida alcance o caiga por debajo de este nivel de agua, se llamará a la devolución de llamada de escritura;

(3.4) Escriba el nivel de agua alto: no lo configure, solo escriba directamente, generalmente no se usa.

De forma predeterminada, el nivel de agua bajo y el nivel de agua alto de lectura son 0, lo que indica que hay datos para leer y no hay límite para el número máximo de lecturas. Lo mismo es cierto para el nivel de agua escrito, lo que significa que si es escribible, todo estará escrito.

 (4) Hay un  parámetro what adicional  en la función de devolución de llamada del evento, que indica el evento que ocurrió:

// 读取错误
#define BEV_EVENT_READING	0x01	/**< error encountered while reading */

// 写入错误
#define BEV_EVENT_WRITING	0x02	/**< error encountered while writing */

// 到达文件结尾
#define BEV_EVENT_EOF		0x10	/**< eof file reached */

// 不可恢复的错误
#define BEV_EVENT_ERROR		0x20	/**< unrecoverable error encountered */

// 到达直到的超时时间
#define BEV_EVENT_TIMEOUT	0x40	/**< user-specified timeout reached */

// 连接操作完成
#define BEV_EVENT_CONNECTED	0x80	/**< connect operation finished. */

Dos, la interfaz básica de bufferevent

Las interfaces de bufferevent se encuentran en el archivo de encabezado <event2/bufferevent.h>.

1. Cree una interfaz de contexto de evento de búfer

struct bufferevent *bufferevent_socket_new(
	struct event_base *base, evutil_socket_t fd, int options);

Descripción de parámetros:

(1) base: contexto libevent;
(2) fd: descriptor de socket, las operaciones de lectura y escritura de bufferevent se basan en este descriptor;
(3) opciones: opcional, definidas de la siguiente manera:

enum bufferevent_options {
	// 释放bufferevent时,关闭底层socket传输
	BEV_OPT_CLOSE_ON_FREE = (1<<0),

	// 线程安全,即在bufferevent中使用lock,此时callback也会被加锁
	BEV_OPT_THREADSAFE = (1<<1),

	// 在事件循环中延迟回调
	BEV_OPT_DEFER_CALLBACKS = (1<<2),

	// 不对回调函数加锁,即便设置了BEV_OPT_THREADSAFE也不加锁
    // 此选项需要与BEV_OPT_DEFER_CALLBACKS一起使用,未来可能会移除这一要求
	BEV_OPT_UNLOCK_CALLBACKS = (1<<3)
};

En general, use la opción BEV_OPT_CLOSE_ON_FREE, lo que significa que el socket también se cerrará cuando bufferevent_free.

2. Habilitar/deshabilitar la operación de eventos de búfer

// 开启
int bufferevent_enable(struct bufferevent *bufev, short event);
// 关闭
int bufferevent_disable(struct bufferevent *bufev, short event);

evento: especifique el evento de habilitación, generalmente eventos de lectura y escritura EV_READ | EV_WRITE;

3. Establecer la función de devolución de llamada de bufferevent

void bufferevent_setcb(struct bufferevent *bufev,
    bufferevent_data_cb readcb, bufferevent_data_cb writecb,
    bufferevent_event_cb eventcb, void *cbarg);

Incluye funciones de devolución de llamada de lectura, escritura y evento tres.

4. Lea el búfer de eventos del búfer

size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); 

Descripción de parámetros:

(1) datos: el búfer para almacenar datos;
(2) tamaño: la longitud del búfer para almacenar datos.

5. Escribir en el búfer de eventos del búfer

int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size); 

Valor devuelto: 0 se devuelve en caso de éxito y -1 se devuelve en caso de error.

6. Establecer el tiempo de espera del evento de búfer

int bufferevent_set_timeouts(struct bufferevent *bufev,
    const struct timeval *timeout_read, const struct timeval *timeout_write); 

Descripción de parámetros:

(1) timeout_read: tiempo de espera de lectura, NULL significa que no hay tiempo de espera;
(2) timeout_write: tiempo de espera de escritura, NULL significa que no hay tiempo de espera.
Valor devuelto: 0 se devuelve en caso de éxito y -1 se devuelve en caso de error.

Puede utilizar los siguientes métodos para determinar si se trata de un tiempo de espera de lectura y escritura:

if ((what & BEV_EVENT_TIMEOUT) && (what & BEV_EVENT_READING)) { /* 读超时 */ }

if ((what & BEV_EVENT_TIMEOUT) && (what & BEV_EVENT_WRITING)) { /* 写超时 */ }

7. Suelte el evento del búfer

void bufferevent_free(struct bufferevent *bufev);

La función bufferevent_free tiene un recuento de referencias dentro y se cerrará lo antes posible, es decir, se cerrará después de que se considere que no hay referencia y no se cerrará inmediatamente. Si se establece el indicador BEV_OPT_CLOSE_ON_FREE, el socket también se cerrará durante bufferevent_free.

Además, debe tenerse en cuenta que si se llama a bufferevent_free inmediatamente después de enviar con bufferevent_write, es posible que no se envíen algunos datos, así que no cierre el evento de buffer antes de tiempo.

8. Conéctese al zócalo del servidor

Generalmente se utiliza para programas cliente.

int bufferevent_socket_connect(struct bufferevent *bufev, 
	const struct sockaddr *addr, int socklen);

El socket fd en el bufferevent debe establecerse en nonblock al llamar a esta función. En circunstancias normales, si la conexión es exitosa, se activará la devolución de llamada del evento BEV_EVENT_CONNECTED.

 

Supongo que te gusta

Origin blog.csdn.net/mars21/article/details/131386362
Recomendado
Clasificación