写在前面:
libevent常规事件的总结使用步骤参考:libevent总结(一)-------libevent常规事件
bufferevent 原理部分和函数分析部分参考:libevent总结(二)-------libevent bufferevent事件
bufferevent实现服务器部分参考: libevent总结(三)-------bufferevent实现server
正文:
一:bufferevent实现客户端流程:
(1): 创建event_base;
(2): 创建 bufferevent 事件对象;client监听的fd是自己本地的fd即可。
(3): bufferevent_socket_connect()连接服务器;
(4): 使用bufferevent_setcb()函数给bufferevent的read、write、event设置回调函数;
(5): 使能bufferevent的读写缓冲区;
(6): bufferevent_read()、bufferevent_write()收发数据;
(7):启动循环监听:event_base_dispatch();
(8): 释放资源
二:代码部分,详见注释:
//读数据回调,要在读回调里面调用bufferevent_read()来完成服务器发送过来数据的读取
void read_cb(struct bufferevent *bev, void *ctx)
{
char buf[1024] = {0x0};
//读取client发过来的数据
int len = bufferevent_read(bev,buf, 1024);
printf("client:received %d byts from server,content is %s\n",len,buf);
sleep(3);
}
//写回调,当bufferevent_write发送成功后,这里会被调用
void write_cb(struct bufferevent *bev, void *ctx)
{
printf("client datas send succeed\n");
}
//事件回调
void event_cb(struct bufferevent *bev, short what, void *ctx)
{
if(what & BEV_EVENT_READING )
{
printf("BEV_EVENT_READING event happend\n");
//次错误发送要释放 bufferevent资源
bufferevent_free(bev);
}
if(what & BEV_EVENT_WRITING )
{
printf("BEV_EVENT_WRITING event happend\n");
//次错误发送要释放 bufferevent资源
bufferevent_free(bev); }
if(what & BEV_EVENT_EOF )
{
printf("BEV_EVENT_EOF event happend\n");
//次错误发送要释放 bufferevent资源
bufferevent_free(bev); }
if(what & BEV_EVENT_ERROR )
{
printf("BEV_EVENT_ERROR event happend\n");
//次错误发送要释放 bufferevent资源
bufferevent_free(bev); }
if(what & BEV_EVENT_TIMEOUT )
{
printf("BEV_EVENT_TIMEOUT event happend\n");
//次错误发送要释放 bufferevent资源
bufferevent_free(bev); }
if(what & BEV_EVENT_CONNECTED )
{
printf("BEV_EVENT_CONNECTED event happend\n");
}
}
void timer_cb(evutil_socket_t fd, short event, void *arg)
{
printf("timer: send data to server\n");
struct bufferevent * bev = (struct bufferevent * )arg;
char *pBuf = "Hello server,this is clint timer to send data for you";
bufferevent_write(bev, pBuf, strlen(pBuf)+1); //注意这个函数执行成功后,我们设置的写回调将会被调用哦
}
int main(void)
{
//创建 event_base
struct event_base * even_base = event_base_new();
//创建 bufferevent 事件对象,通信的fd放到bufferevent中,客户端只需要监听自己本地的fd即可
int fd = socket(AF_INET,SOCK_STREAM,0); //用socket创建一个fd
struct bufferevent * bev = bufferevent_socket_new(even_base, fd,BEV_OPT_CLOSE_ON_FREE);
//打包服务器地址信息
struct sockaddr_in serv;
memset(serv,0,sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = honts(5678);
inet_pton(AF_INET,"172.168.1.10",&serv.sin_addr.s_addr);
//连接服务器
bufferevent_socket_connect(bev,serv, sizeof(serv));
//设置回调:
//因为client监听的是自己的fd所以client有没有连接成功都可以设置回调来监听读写数据
bufferevent_setcb(bev,read_cb, write_cb, event_cb, NULL);
//使能读写缓冲区
bufferevent_enable(bev, EV_READ|EV_WRITE);
//创建一个定时器事件,这里定时给服务器发送数据,并将bufferevent 作为参数给 timer_cb使用
//因为在timer_cb中会调用 bufferevent_write()发送数据给server
struct event * event = event_new(even_base, -1, EV_TIMEOUT|EV_PERSIST,timer_cb,bev);
//添加事件
struct hal_timeval tv;
tv.tv_sec = 10; //设置时间为10s
tv.tv_usec = 0;
event_add(event, &tv);
//启动循环监听
event_base_dispatch(even_base);
//释放资源
event_base_free(even_base);
return 0;
}