The basics of libevent(12) bufferevent

1. The basic concept of bufferevent

bufferevent is an event buffer IO in libevent, which implements basic socket recv/send operations internally. Users only need to call the bufferevent API to read and write data.

(1) Buffer: Each bufferevent has a read buffer (input) and a write buffer (output). The data structure is evbuffer, which is a data buffer for buffering data sent or received on the network.

(2) Callback:

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

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

(3) Water level: The call of the callback function can be adjusted by setting the water level.

(3.1) Read the low water level: when the data volume of the input buffer reaches or exceeds this water level, the callback function will be called, that is, if the data volume does not meet the water level requirement, the callback will not be called;

(3.2) Read high water level: When the data volume of the input buffer reaches this water level, bufferevent will stop reading until the data in the input buffer is read, making the data volume lower than this water level. Note used to limit the maximum amount of data read at one time.

(3.3) Write low water level: when the amount of data in the output buffer reaches or falls below this water level, the write callback will be called;

(3.4) Write high water level: Do not set, just write directly, generally not used.

By default, the read low water level and high water level are both 0, indicating that there is data to read, and there is no limit to the maximum number of reads. The same is true for the written water level, which means that if it is writable, all will be written.

 (4) There is an additional  what  parameter in the event callback function, indicating the event that occurred:

// 读取错误
#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. */

Two, the basic interface of bufferevent

The interfaces of bufferevent are located in the header file <event2/bufferevent.h>.

1. Create a bufferevent context interface

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

Parameter Description:

(1) base: libevent context;
(2) fd: socket descriptor, the read and write operations of bufferevent are based on this descriptor;
(3) options: optional, defined as follows:

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)
};

Generally use the BEV_OPT_CLOSE_ON_FREE option, which means that the socket will also be closed when bufferevent_free.

2. Enable/disable bufferevent operation

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

event: Specify the enable event, generally read and write events EV_READ | EV_WRITE;

3. Set the callback function of bufferevent

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

Including read, write, event three callback functions.

4. Read the bufferevent buffer

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

Parameter Description:

(1) data: the buffer for storing data;
(2) size: the length of the buffer for storing data.

5. Write to the bufferevent buffer

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

Return value: 0 is returned on success, and -1 is returned on failure.

6. Set bufferevent timeout

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

Parameter Description:

(1) timeout_read: read timeout, NULL means no timeout;
(2) timeout_write: write timeout, NULL means no timeout.
Return value: 0 is returned on success, and -1 is returned on failure.

You can use the following methods to determine whether it is a read-write timeout:

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

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

7. Release bufferevent

void bufferevent_free(struct bufferevent *bufev);

The bufferevent_free function has a reference count inside, and it will be closed as soon as possible, that is, it will be closed after it is judged that there is no reference, and it will not be closed immediately. If the BEV_OPT_CLOSE_ON_FREE flag is set, the socket will also be closed during bufferevent_free.

In addition, it should be noted that if bufferevent_free is called immediately after sending with bufferevent_write, some data may not be sent out, so do not close the bufferevent prematurely.

8. Connect to the server socket

Generally used for client programs.

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

The socket fd in the bufferevent must be set to nonblock when calling this function. Under normal circumstances, if the connection is successful, the event callback of BEV_EVENT_CONNECTED will be triggered.

 

Guess you like

Origin blog.csdn.net/mars21/article/details/131386362