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 表名区分大小写

    原来Linux下的MySQL默认是区分表名大小写的,通过如下设置,可以让MySQL不区分表名大小写:1.用root登录,修改 /etc/my.cnf:2.在[mysqld]节点下,加入一行: lowe ...

  2. WEB测试—用户界面测试

    如果有设计稿,当然按照设计稿进行测试:没有设计稿,就参考原型:如果都没有,就按照web大众排版设计要求测试了,当然,还是要产品看过为准. 一下简单总结一下测试的点. 1. 导航测试 很少有用户愿意花时 ...

  3. c#返回值的理解

    我感觉没什么用...就是在别的地方用的时候可以直接以Add(a,b)这样的方式赋值就行,不用再用c这个中间变量去接收了,希望有一天有大佬能给我讲讲设置返回值有什么好处

  4. EF Core 2.1 中的 Eager loading、Explicit loading和LazyLoading (转自MSDN)

    Entity Framework Core allows you to use the navigation properties in your model to load related enti ...

  5. win7下添加库文件出现“file is not regcognized”问题

    最近几天需要画电路图,所以安装了protel se99,安装后在添加库文件的时候出现“file is not regcognized”的问题 百度查了一下,说win7基本上都会出现这个问题. 实际上, ...

  6. Spring Boot集成Hazelcast实现集群与分布式内存缓存

    Hazelcast是Hazelcast公司开源的一款分布式内存数据库产品,提供弹性可扩展.高性能的分布式内存计算.并通过提供诸如Map,Queue,ExecutorService,Lock和JCach ...

  7. 【微信开发】LINUX-windows下用navicat远程链接虚拟机Linux下MySQL数据库

    今天想用navicat远程连接虚拟机中的MySQL数据库,一直连不上,在网上搜索了一下,发现原因是MySQL对远程用户登陆的授权问题.   MySQL登陆:mysql -h主机地址 -u用户名-p用户 ...

  8. JAVA中时间格式转换

    1.将任意日期格式的字符串转换为指定格式的字符串 //默认格式 String s1 = "20190110133236"; //给定格式 String s2 = "201 ...

  9. oracle中的事务

     事务 概述:通过sql 对数据库进行操作时,同时执行成功或失败,且数据完整性一致. 链接到oracle的用户(例如plsql或sqlplus)会形成一个session, 此时对数据库的更新操作,不会 ...

  10. SpringBoot使用maven插件打包時報:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException的處理方案

    SpringBoot使用maven插件打包時報:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExec ...