Libevent库基础(2)
带缓冲区的事件 bufferevent
#include <event2/bufferevent.h>
read/write 两个缓冲. 借助 队列.
创建、销毁bufferevent:
struct bufferevent *ev;
struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, enum bufferevent_options options);
base: event_base
fd: 封装到bufferevent内的 fd
options:BEV_OPT_CLOSE_ON_FREE
返回: 成功创建的 bufferevent事件对象。
void bufferevent_socket_free(struct bufferevent *ev);
给bufferevent设置回调:
对比event: event_new( fd, callback ); event_add() -- 挂到 event_base 上。
bufferevent_socket_new(fd) bufferevent_setcb( callback )
void bufferevent_setcb(struct bufferevent * bufev,
bufferevent_data_cb readcb,
bufferevent_data_cb writecb,
bufferevent_event_cb eventcb,
void *cbarg );
bufev: bufferevent_socket_new() 返回值
readcb: 设置 bufferevent 读缓冲,对应回调 read_cb{ bufferevent_read() 读数据 }
writecb: 设置 bufferevent 写缓冲,对应回调 write_cb { } -- 给调用者,发送写成功通知。 可以 NULL
eventcb: 设置 事件回调。 也可传NULL
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *ctx);
void event_cb(struct bufferevent *bev, short events, void *ctx)
{
。。。。。
}
events: BEV_EVENT_CONNECTED
cbarg: 上述回调函数使用的 参数。
read 回调函数类型:
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void*ctx);
void read_cb(struct bufferevent *bev, void *cbarg )
{
.....
bufferevent_read(); --- read();
}
bufferevent_read()函数的原型:
size_t bufferevent_read(struct bufferevent *bev, void *buf, size_t bufsize);
write 回调函数类型:
int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
启动、关闭 bufferevent的 缓冲区:
void bufferevent_enable(struct bufferevent *bufev, short events); 启动
events: EV_READ、EV_WRITE、EV_READ|EV_WRITE
默认、write 缓冲是 enable、read 缓冲是 disable
bufferevent_enable(evev, EV_READ); -- 开启读缓冲
连接客户端:
socket();connect();
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);
bev: bufferevent 事件对象(封装了fd)
address、len:等同于 connect() 参2/3
创建监听服务器:
------ socket();bind();listen();accept();
struct evconnlistener * listner;
struct evconnlistener *evconnlistener_new_bind (
struct event_base *base,
evconnlistener_cb cb,
void *ptr,
unsigned flags,
int backlog,
const struct sockaddr *sa,
int socklen);
base: event_base
cb: 回调函数。 一旦被回调,说明在其内部应该与客户端完成, 数据读写操作,进行通信。
ptr: 回调函数的参数
flags: LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE
backlog: listen() 2参。 -1 表最大值
sa:服务器自己的地址结构体
socklen:服务器自己的地址结构体大小。
返回值:成功创建的监听器。
释放监听服务器:
void evconnlistener_free(struct evconnlistener *lev);
服务器端 libevent 创建TCP连接:
1. 创建event_base
2. 创建bufferevent事件对象。bufferevent_socket_new();
3. 使用bufferevent_setcb() 函数给 bufferevent的 read、write、event 设置回调函数。
4. 当监听的 事件满足时,read_cb会被调用, 在其内部 bufferevent_read();读
5. 使用 evconnlistener_new_bind 创建监听服务器, 设置其回调函数,当有客户端成功连接时,这个回调函数会被调用。
6. 封装 listner_cb() 在函数内部。完成与客户端通信
7. 设置读缓冲、写缓冲的 使能状态 enable、disable
8.启动循环 event_base_dispath();
9.释放连接
客户端端 libevent 创建TCP连接:
1、event_base
2. 创建bufferevent事件对象。bufferevent_socket_new();
3、bufferevent_socket_connect()连接服务器
4、使用bufferevent_setcb()函数给 bufferevent的 read、write、event 设置回调函数
5、设置读缓冲、写缓冲的 使能状态 enable、disable
6、接收和发送数据bufferevent_read()/bufferevent_write()
7、启动循环 event_base_dispath();
8、释放连接
libevent的服务器代码:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <string.h> 7 #include <event2/event.h> 8 #include <event2/listener.h> 9 #include <event2/bufferevent.h> 10 11 // 读缓冲区回调 12 void read_cb(struct bufferevent *bev, void *arg) 13 { 14 char buf[1024] = {0}; 15 bufferevent_read(bev, buf, sizeof(buf)); 16 printf("client say: %s\n", buf); 17 18 char *p = "我是服务器, 已经成功收到你发送的数据!"; 19 // 发数据给客户端 20 bufferevent_write(bev, p, strlen(p)+1); 21 sleep(1); 22 } 23 24 // 写缓冲区回调 25 void write_cb(struct bufferevent *bev, void *arg) 26 { 27 printf("I'm服务器, 成功写数据给客户端,写缓冲区回调函数被回调...\n"); 28 } 29 30 // 事件 31 void event_cb(struct bufferevent *bev, short events, void *arg) 32 { 33 if (events & BEV_EVENT_EOF) 34 { 35 printf("connection closed\n"); 36 } 37 else if(events & BEV_EVENT_ERROR) 38 { 39 printf("some other error\n"); 40 } 41 42 bufferevent_free(bev); 43 printf("buffevent 资源已经被释放...\n"); 44 } 45 46 47 48 void cb_listener( 49 struct evconnlistener *listener, 50 evutil_socket_t fd, 51 struct sockaddr *addr, 52 int len, void *ptr) 53 { 54 printf("connect new client\n"); 55 56 struct event_base* base = (struct event_base*)ptr; 57 // 通信操作 58 // 添加新事件 59 struct bufferevent *bev; 60 bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); 61 62 // 给bufferevent缓冲区设置回调 63 bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL); 64 bufferevent_enable(bev, EV_READ); 65 } 66 67 68 int main(int argc, const char* argv[]) 69 { 70 71 // init server 72 struct sockaddr_in serv; 73 74 memset(&serv, 0, sizeof(serv)); 75 serv.sin_family = AF_INET; 76 serv.sin_port = htons(9876); 77 serv.sin_addr.s_addr = htonl(INADDR_ANY); 78 79 struct event_base* base; 80 base = event_base_new(); 81 // 创建套接字 82 // 绑定 83 // 接收连接请求 84 struct evconnlistener* listener; 85 listener = evconnlistener_new_bind(base, cb_listener, base, 86 LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 87 36, (struct sockaddr*)&serv, sizeof(serv)); 88 89 event_base_dispatch(base); 90 91 evconnlistener_free(listener); 92 event_base_free(base); 93 94 return 0; 95 }
libevent客户端代码:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <string.h> 7 #include <event2/bufferevent.h> 8 #include <event2/event.h> 9 #include <arpa/inet.h> 10 11 void read_cb(struct bufferevent *bev, void *arg) 12 { 13 char buf[1024] = {0}; 14 bufferevent_read(bev, buf, sizeof(buf)); 15 16 printf("fwq say:%s\n", buf); 17 18 bufferevent_write(bev, buf, strlen(buf)+1); 19 sleep(1); 20 } 21 22 void write_cb(struct bufferevent *bev, void *arg) 23 { 24 printf("----------我是客户端的写回调函数,没卵用\n"); 25 } 26 27 void event_cb(struct bufferevent *bev, short events, void *arg) 28 { 29 if (events & BEV_EVENT_EOF) 30 { 31 printf("connection closed\n"); 32 } 33 else if(events & BEV_EVENT_ERROR) 34 { 35 printf("some other error\n"); 36 } 37 else if(events & BEV_EVENT_CONNECTED) 38 { 39 printf("已经连接服务器...\\(^o^)/...\n"); 40 return; 41 } 42 43 // 释放资源 44 bufferevent_free(bev); 45 } 46 47 // 客户端与用户交互,从终端读取数据写给服务器 48 void read_terminal(evutil_socket_t fd, short what, void *arg) 49 { 50 // 读数据 51 char buf[1024] = {0}; 52 int len = read(fd, buf, sizeof(buf)); 53 54 struct bufferevent* bev = (struct bufferevent*)arg; 55 // 发送数据 56 bufferevent_write(bev, buf, len+1); 57 } 58 59 int main(int argc, const char* argv[]) 60 { 61 struct event_base* base = NULL; 62 base = event_base_new(); 63 64 int fd = socket(AF_INET, SOCK_STREAM, 0); 65 66 // 通信的fd放到bufferevent中 67 struct bufferevent* bev = NULL; 68 bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); 69 70 // init server info 71 struct sockaddr_in serv; 72 memset(&serv, 0, sizeof(serv)); 73 serv.sin_family = AF_INET; 74 serv.sin_port = htons(9876); 75 inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr); 76 77 // 连接服务器 78 bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv)); 79 80 // 设置回调 81 bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL); 82 83 // 设置读回调生效 84 // bufferevent_enable(bev, EV_READ); 85 86 // 创建事件 87 struct event* ev = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST, 88 read_terminal, bev); 89 // 添加事件 90 event_add(ev, NULL); 91 92 event_base_dispatch(base); 93 94 event_free(ev); 95 96 event_base_free(base); 97 98 return 0; 99 }

浙公网安备 33010602011771号