1.evbuffer以队列的形式管理字节,从尾部添加,从头部取出(FIFO)
2.evbuffer内部存储形式是多个独立的连续内存
 
 
 
接口
//创建和删除
struct evbuffer *evbuffer_new(void);
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_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);
 
//在首部添加数据
//这些函数不应该用于和bufferevent关联的evbuffer
int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size);
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);
 
//从首部拷贝而不删除数据
//如果效率不好可以使用 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);
 
//按行进行读写
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);
 
//在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);
 
 
//偏移位置计算标示
//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);
 
 
//搜索所有的字符串
#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;
}

 
 
//在不使用拷贝的情况下,直接查看evbuffer的数据
struct evbuffer_iovec {
        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);
 
//如果获取到指针后,有修改evbuffer数据的行为,将导致指针失效
//或者的指针的值不能被修改
//如果evbuffer以及有数据则,这些数据将加到已有数据的后面
 
//将数据提交的evbuffer
int evbuffer_commit_space(struct evbuffer *buf,
    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);
 
 
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);

 
//设置回调函数
struct evbuffer_cb_entry;
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);

//使用 EVBUFFER_CB_ENABLED失效

#define EVBUFFER_CB_ENABLED 1
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);

 
 
//延迟回调函数的调用
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);

 
 
//直接发送文件相关接口,由于支持的版本很新,目前未测试
 
int evbuffer_add_file(struct evbuffer *output, int fd, ev_off_t offset,
    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);

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

 
 
int evbuffer_add_buffer_reference(struct evbuffer *outbuf,
    struct evbuffer *inbuf);
 
 
int evbuffer_freeze(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);
 
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);
 
 
 
 

libevent学习八(evbuffer)的更多相关文章

  1. libevent学习之二:Windows7(Win7)下编译libevent

    Linux下编译参考源码中的README文件即可,这里主要记录Windows下的编译. 一.准备工作 去官网下载最新的稳定发布版本libevent-2.0.22-stable 官网地址:http:// ...

  2. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  3. SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  4. libevent学习笔记 一、基础知识【转】

    转自:https://blog.csdn.net/majianfei1023/article/details/46485705 欢迎转载,转载请注明原文地址:http://blog.csdn.net/ ...

  5. Libevent学习笔记(五) 根据例子学习bufferevent

    libevent中提供了一个Hello-world.c 的例子,从这个例子可以学习libevent是如何使用bufferevent的. 这个例子在Sample中 这个例子之前讲解过,这次主要看下buf ...

  6. libevent学习笔记(参考libevent深度剖析)

    最近自学libevent事件驱动库,参考的资料为libevent2.2版本以及张亮提供的<Libevent源码深度剖析>, 参考资料: http://blog.csdn.net/spark ...

  7. 【传智播客】Libevent学习笔记(一):简介和安装

    目录 00. 目录 01. libevent简介 02. Libevent的好处 03. Libevent的安装和测试 04. Libevent成功案例 00. 目录 @ 01. libevent简介 ...

  8. PHP中的Libevent学习

    wangbin@2012,1,3 目录 Libevent在php中的应用学习 1.      Libevent介绍 2.      为什么要学习libevent 3.      Php libeven ...

  9. Libevent学习之SocketPair实现

    Libevent设计的精化之一在于把Timer事件.Signal事件和IO事件统一集成在一个Reactor中,以统一的方式去处理这三种不同的事件,更确切的说是把Timer事件和Signal事件融合到了 ...

随机推荐

  1. mysql的入门基本使用(适合新手学习)

    登陆Mysql数据库mysql -u root -p 展示(查询)所有数据库show databases;进入数据库use dataname;创建数据库create database dataname ...

  2. 【题解】洛谷P1120 小木棍(搜索+剪枝+卡常)

    洛谷P1120:https://www.luogu.org/problemnew/show/P1120 思路 明显是搜索题嘛 但是这数据增强不是一星半点呐 我们需要N多的剪枝 PS:需要先删去超出50 ...

  3. 一点一点看JDK源码(五)java.util.ArrayList 后篇之Spliterator多线程遍历

    一点一点看JDK源码(五)java.util.ArrayList 后篇之Spliterator多线程遍历 liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看J ...

  4. STL笔记

    STL的基本概念: 1-容器:是可容纳各种类型的数据结构,是 类模板. 2-迭代器:是用于依次存放容器中的元素,类似指针. 3-算法: 是用于操作容器中元素的 函数模板. sort() 用来对 vec ...

  5. Linux下Git远程仓库的使用详解

    Git远程仓库Github 提示:Github网站作为远程代码仓库时的操作和本地代码仓库一样的,只是仓库位置不同而已! 准备Git源代码仓库 https://github.com/ 准备经理的文件 D ...

  6. git获取步骤

    $ git init $ git config --global user.name "[name]" $ git config --global user.email [emai ...

  7. SpringBoot整合Eureka搭建微服务

    1.创建一个services项目,添加三个子模块client(客户端).service(服务端).registry(注册中心) 1.1 创建一个services项目 1.2 添加pom.xml依赖 & ...

  8. 部署laravel项目

    1 先登录到服务器上,将代码克隆下来 git clone 项目地址 2 避免composer太慢,启用本镜像服务 可以先安装 apt-get install zip,unzip,php7.0-zip ...

  9. hadoop生态搭建(3节点)-13.mongodb配置

    # 13.mongodb配置_副本集_认证授权# ==================================================================安装 mongod ...

  10. Java开发小技巧(五):HttpClient工具类

    前言 大多数Java应用程序都会通过HTTP协议来调用接口访问各种网络资源,JDK也提供了相应的HTTP工具包,但是使用起来不够方便灵活,所以我们可以利用Apache的HttpClient来封装一个具 ...