现在的位置: 首页 > 综合 > 正文

Libevent中读消息流程

2013年04月24日 ⁄ 综合 ⁄ 共 2838字 ⁄ 字号 评论关闭

关于接收监听并建立连接得到通讯套接字过程请参考Libevent监听事件的建立过程文档。

涉及到的几个结构体

 

struct bufferevent_private

{

         //主要的结构体

                   structbufferevent bev;

                   structevbuffer_cb_entry *read_watermarks_cb;

                   unsignedown_lock : 1;

         //为简化省略了一些变量声明

            struct bufferevent_rate_limit*rate_limiting;

};

struct event_watermark

{

         size_t low;

         size_t high;

};

struct bufferevent

 {

         structevent_base *ev_base;    

         const
struct
bufferevent_ops *be_ops;    

         struct
event
ev_read;        

         struct
event
ev_write;       

         structevbuffer *input;     

         structevbuffer *output;

         structevent_watermark wm_read;

         structevent_watermark wm_write;

    //回调函数

         bufferevent_data_cb readcb;

         bufferevent_data_cb writecb;

         bufferevent_event_cb errorcb;

    //回调参数

         void*cbarg;

         structtimeval timeout_read;

         structtimeval timeout_write;

    //事件类型

         shortenabled;

};

 

 

在监听回调事件中代码如下:

static voidlistener_cb(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *sa,
int socklen, void*user_data)

{

         structevent_base *base = (struct event_base*)user_data;

         structbufferevent *bev;    

         bev = bufferevent_socket_new(base, fd,BEV_OPT_CLOSE_ON_FREE);      

         bufferevent_setcb(bev, conn_readcb,conn_writecb, conn_eventcb, NULL);

         bufferevent_enable(bev,EV_WRITE|EV_READ);

}

1.先来看看bufferevent_socket_new函数。

struct bufferevent *

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

{

   //创建bufferevent_private结构体

   // bufferevent_init_common对该结构体进行参数初始化,在该函数中,

   // 通过bufev->input= evbuffer_new()语句新建evbuffer并赋值。

   //传递函数指针struct bufferevent_ops  给bufferevent

   bufferevent_init_common(bufev_p, base,&bufferevent_ops_socket,options)

   //对bufferevent中的读写事件赋值

 event_assign(&bufev->ev_read,bufev->ev_base, fd,EV_READ|EV_PERSIST, bufferevent_readcb, bufev);

event_assign(&bufev->ev_write,bufev->ev_base, fd,EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev);

//设置输入输出缓冲的释放顺序标志

//将buffevevent返回

}

2. bufferevent_setcb(bev, conn_readcb,conn_writecb, conn_eventcb, NULL);

将回调函数设置到bufferevent结构体上。内部进行了线程保护。

3.bufferevent_enable(bev, EV_WRITE|EV_READ)

调用指针结构体的be_socket_enable(struct bufferevent *bufev,
shortevent)

该函数内部又调用be_socket_add(&bufev->ev_read,&bufev->timeout_read)

该函数内部又调用event_add(ev,NULL);

该函数内部又调用event_add_internal(ev,tv, 0);

最后将该事件增加到eventBase的哈希表中,并增加到底层监听结构里。

注意读写事件时分别增加的事件,所以一个fd如果要支持读和写的功能,需要增加2个事件。

4. 回调处理

在event_assign函数中读回调用的是bufferevent_readcb,因此当读事件发生时,调用的是bufferevent_readcb函数。

在该函数中

//获取最大可以读取的字节数

readmax =_bufferevent_get_read_max(bufev_p);

//读取数据

res =evbuffer_read(input, fd, (int)howmuch);

//调用用户回调函数

_bufferevent_run_readcb(bufev);

//调用回调

bufev->readcb(bufev,bufev->cbarg);

5.读取过程

     struct evbuffer *input =bufferevent_get_input(bev);

         memset(buf,0,sizeof(buf));

         sz=evbuffer_get_length(input);

         if (sz> 0)

         {

                   bufferevent_read(bev,buf,sz);

     }

 

 

 

抱歉!评论已关闭.