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 }

 

posted @ 2020-06-12 13:37  BK-rewrite  阅读(219)  评论(0)    收藏  举报