1.evbuffer以隊列的形式管理字節,從尾部添加,從頭部取出(FIFO)
2.evbuffer內部存儲形式是多個獨立的連續內存
接口
//創建和刪除
struct evbuffer *evbuffer_new(void);
void evbuffer_free(struct evbuffer *buf);
void evbuffer_free(struct evbuffer *buf);
//加鎖解鎖
//默認情況下是沒有加鎖的,多線程並發訪問不安全
//第二個參數lock為空,則自動分配一個鎖( 使用evthread_set_lock_creation_callback()設置的鎖創建函數)
int evbuffer_enable_locking(struct evbuffer *buf, void *lock);
//沒有必要為單獨的操作加鎖,因為單獨的操作已經是原子級別的了
void evbuffer_lock(struct evbuffer *buf);
void evbuffer_unlock(struct evbuffer *buf);
//獲取evbuffer包含的字節數
size_t evbuffer_get_length(const struct evbuffer *buf);
//獲取隊列首部的連續空間長度
size_t evbuffer_get_contiguous_space(const struct evbuffer *buf);
//基礎的讀寫數據接口
//將數據添加到尾部
int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);
//格式化的添加數據到尾部
int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap);
int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap);
//修改最后一塊連續內存,或者添加一塊連續內存
int evbuffer_expand(struct evbuffer *buf, size_t datlen);
//從evbuffer移動數據到另一個evbuffer
int evbuffer_add_buffer(struct evbuffer *dst, struct evbuffer *src);
int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
size_t datlen);
int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
size_t datlen);
//在首部添加數據
//這些函數不應該用於和bufferevent關聯的evbuffer
int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size);
int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src);
int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src);
//查看首部N字節的連續空間(首先必須確定這N字節空間是連續的,使用
evbuffer_get_contiguous_space ()
)
//size參數為負數,則拷貝首部連續空間的所有數據
//如果size很大,該接口效率低
unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size);
//從evbuffer刪除數據
//evbuffer_drain不拷貝數據,evbuffer_remove要拷貝數據
int evbuffer_drain(struct evbuffer *buf, size_t len);
int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
//從首部拷貝而不刪除數據
//如果效率不好可以使用 evbuffer_peek()
ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data, size_t datlen);
ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf,
const struct evbuffer_ptr *pos,
void *data_out, size_t datlen);
ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf,
const struct evbuffer_ptr *pos,
void *data_out, size_t datlen);
//按行進行讀寫
enum evbuffer_eol_style {
EVBUFFER_EOL_ANY, //已任何序列為換行符
EVBUFFER_EOL_CRLF, //回車換行的組合為換行標示 (\r\n或者\n)
EVBUFFER_EOL_CRLF_STRICT, //嚴格的\r\n
EVBUFFER_EOL_LF, //以\n為換行標示
EVBUFFER_EOL_NUL //以NULL為換行標示
};
//返回的指針在堆上分配,n_read_out參數也是返回參數
char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
enum evbuffer_eol_style eol_style);
enum evbuffer_eol_style eol_style);
//在evbuffer中搜索
//表示位置的結構(pos是相對於開始位置的偏移值)
struct evbuffer_ptr { ev_ssize_t pos; struct { /* internal fields */ } _internal; };
struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer,
const char *what, size_t len, const struct evbuffer_ptr *start);
struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer,
const char *what, size_t len, const struct evbuffer_ptr *start,
const struct evbuffer_ptr *end);
struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer,
struct evbuffer_ptr *start, size_t *eol_len_out,
enum evbuffer_eol_style eol_style);
const char *what, size_t len, const struct evbuffer_ptr *start);
struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer,
const char *what, size_t len, const struct evbuffer_ptr *start,
const struct evbuffer_ptr *end);
struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer,
struct evbuffer_ptr *start, size_t *eol_len_out,
enum evbuffer_eol_style eol_style);
//偏移位置計算標示
//EVBUFFER_PTR_SET,將位置作為絕對位置來設置
//EVBUFFER_PTR_ADD,在當前位置加上參數指定的位置
enum evbuffer_ptr_how {
EVBUFFER_PTR_SET,
EVBUFFER_PTR_ADD
};
int evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *pos,
size_t position, enum evbuffer_ptr_how how);
EVBUFFER_PTR_SET,
EVBUFFER_PTR_ADD
};
int evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *pos,
size_t position, enum evbuffer_ptr_how how);
//搜索所有的字符串
#include <event2/buffer.h>
#include <string.h>
/* Count the total occurrences of 'str' in 'buf'. */int count_instances(struct evbuffer *buf, const char *str)
{
size_t len = strlen(str);
int total = 0;
struct evbuffer_ptr p;
if (!len)
/* Don't try to count the occurrences of a 0-length string. */
return -1;
evbuffer_ptr_set(buf, &p, 0, EVBUFFER_PTR_SET);
while (1) {
p = evbuffer_search(buf, str, len, &p);
if (p.pos < 0)
break;
total++;
evbuffer_ptr_set(buf, &p, 1, EVBUFFER_PTR_ADD);
}
return total;
}
#include <string.h>
/* Count the total occurrences of 'str' in 'buf'. */int count_instances(struct evbuffer *buf, const char *str)
{
size_t len = strlen(str);
int total = 0;
struct evbuffer_ptr p;
if (!len)
/* Don't try to count the occurrences of a 0-length string. */
return -1;
evbuffer_ptr_set(buf, &p, 0, EVBUFFER_PTR_SET);
while (1) {
p = evbuffer_search(buf, str, len, &p);
if (p.pos < 0)
break;
total++;
evbuffer_ptr_set(buf, &p, 1, EVBUFFER_PTR_ADD);
}
return total;
}
//在不使用拷貝的情況下,直接查看evbuffer的數據
struct evbuffer_iovec {
void *iov_base;
size_t iov_len;
};
struct evbuffer_ptr *start_at,
struct evbuffer_iovec *vec_out, int n_vec);
void *iov_base;
size_t iov_len;
};
//修改被evbuffer_iovec指向的數據,將導致未定義行為
//任何修改evbuffer的函數被調用,將導致evbuffer_peek設置的指針失效
int evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len,struct evbuffer_ptr *start_at,
struct evbuffer_iovec *vec_out, int n_vec);
//直接向evbuffer寫入數據,不存在數據拷貝
//獲取evbuffer的內部指針,如果目前的空間不夠,將會進行自動擴展
//目前的實現將不會使用多於兩個的evbuffer_iovec
//如果提供一個evbuffer_iovec則會進行空間連續校驗,以及導致evbuffer調整內部存儲,所以最好提供大於1個的evbuffer_iovec
int evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size,
struct evbuffer_iovec *vec, int n_vecs);
struct evbuffer_iovec *vec, int n_vecs);
//如果獲取到指針后,有修改evbuffer數據的行為,將導致指針失效
//或者的指針的值不能被修改
//如果evbuffer以及有數據則,這些數據將加到已有數據的后面
//將數據提交的evbuffer
int evbuffer_commit_space(struct evbuffer *buf,
struct evbuffer_iovec *vec, int n_vecs);
struct evbuffer_iovec *vec, int n_vecs);
網絡IO
//howmuch參數為負 對於讀表示讀多少由libevent自行判斷,對於寫表示寫整個buffer的內容
//讀到結尾返回值為0,返回負數表示失敗,失敗的原因應進一步確認,是非阻塞IO不能立即完成
//還是其他真實錯誤
//如果使用bufferevent則這些調用都由bufferevent完成,不需要用戶調用
int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd);
int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
ev_ssize_t howmuch);
int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch);
int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
ev_ssize_t howmuch);
int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch);
Evbuffer and callback
//當數據增加或刪除時的回調函數
struct evbuffer_cb_info {
size_t orig_size;//變化前的長度
size_t n_added; //添加的長度
size_t n_deleted; //刪除的長度
};
typedef void (*evbuffer_cb_func)(struct evbuffer *buffer,
const struct evbuffer_cb_info *info, void *arg);
size_t orig_size;//變化前的長度
size_t n_added; //添加的長度
size_t n_deleted; //刪除的長度
};
typedef void (*evbuffer_cb_func)(struct evbuffer *buffer,
const struct evbuffer_cb_info *info, void *arg);
//設置回調函數
struct evbuffer_cb_entry;
struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer,
evbuffer_cb_func cb, void *cbarg);
struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer,
evbuffer_cb_func cb, void *cbarg);
//失效或刪除回調函數
int evbuffer_remove_cb_entry(struct evbuffer *buffer,
struct evbuffer_cb_entry *ent);
int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb,
void *cbarg);
int evbuffer_cb_set_flags(struct evbuffer *buffer,
struct evbuffer_cb_entry *cb,
ev_uint32_t flags);
int evbuffer_cb_clear_flags(struct evbuffer *buffer,
struct evbuffer_cb_entry *cb,
ev_uint32_t flags);
struct evbuffer_cb_entry *ent);
int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb,
void *cbarg);
//使用
EVBUFFER_CB_ENABLED失效
#define EVBUFFER_CB_ENABLED 1int evbuffer_cb_set_flags(struct evbuffer *buffer,
struct evbuffer_cb_entry *cb,
ev_uint32_t flags);
int evbuffer_cb_clear_flags(struct evbuffer *buffer,
struct evbuffer_cb_entry *cb,
ev_uint32_t flags);
//延遲回調函數的調用
int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base);
//避免數據拷貝的 基本的ebuffer-IO
typedef void (*evbuffer_ref_cleanup_cb)(const void *data,
size_t datalen, void *extra);
int evbuffer_add_reference(struct evbuffer *outbuf,
const void *data, size_t datlen,
evbuffer_ref_cleanup_cb cleanupfn, void *extra);
size_t datalen, void *extra);
int evbuffer_add_reference(struct evbuffer *outbuf,
const void *data, size_t datlen,
evbuffer_ref_cleanup_cb cleanupfn, void *extra);
//直接發送文件相關接口,由於支持的版本很新,目前未測試
int evbuffer_add_file(struct evbuffer *output, int fd, ev_off_t offset,
size_t length);
size_t length);
struct evbuffer_file_segment;
struct evbuffer_file_segment *evbuffer_file_segment_new(
int fd, ev_off_t offset, ev_off_t length, unsigned flags);
void evbuffer_file_segment_free(struct evbuffer_file_segment *seg);
int evbuffer_add_file_segment(struct evbuffer *buf,
struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length);
struct evbuffer_file_segment *evbuffer_file_segment_new(
int fd, ev_off_t offset, ev_off_t length, unsigned flags);
void evbuffer_file_segment_free(struct evbuffer_file_segment *seg);
int evbuffer_add_file_segment(struct evbuffer *buf,
struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length);
typedef void (*evbuffer_file_segment_cleanup_cb)(
struct evbuffer_file_segment const *seg, int flags, void *arg);
void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg,
evbuffer_file_segment_cleanup_cb cb, void *arg);
struct evbuffer_file_segment const *seg, int flags, void *arg);
void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg,
evbuffer_file_segment_cleanup_cb cb, void *arg);
int evbuffer_add_buffer_reference(struct evbuffer *outbuf,
struct evbuffer *inbuf);
struct evbuffer *inbuf);
int evbuffer_freeze(struct evbuffer *buf, int at_front);
int evbuffer_unfreeze(struct evbuffer *buf, int at_front);
int evbuffer_unfreeze(struct evbuffer *buf, int at_front);
//過時的接口
char *evbuffer_readline(struct evbuffer *buffer);
unsigned char *evbuffer_find(struct evbuffer *buffer,
const unsigned char *what, size_t len);
unsigned char *evbuffer_find(struct evbuffer *buffer,
const unsigned char *what, size_t len);
typedef void (*evbuffer_cb)(struct evbuffer *buffer,
size_t old_len, size_t new_len, void *arg);
void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg);
size_t old_len, size_t new_len, void *arg);
void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg);