libevent案例

约定不等于承诺〃 2022-12-11 13:57 286阅读 0赞

文章目录

  • 常规事件
  • 缓冲事件

常规事件

server

  1. #include <sys/stat.h>
  2. #include <unistd.h>
  3. #include <fcntl.h>
  4. #include <event2/event.h>
  5. void read_cb(evutil_socket_t fd, short what, void *arg) {
  6. char buf[1024];
  7. int len = read(fd, buf, sizeof(buf));
  8. printf("%s \n", what & EV_READ ? "yes" : "no");
  9. printf("%s %d \n", buf, len);
  10. sleep(1);
  11. }
  12. int main() {
  13. unlink("myfifo");
  14. mkfifo("myfifo", 0664);
  15. /**
  16. * 获取读权限,设置非阻塞.
  17. * 这里之所以非阻塞是因为libevent是基于事件异步的通行模型,主要异步执行回调函数.
  18. */
  19. int fd = open("myfifo", O_RDONLY | O_NONBLOCK);
  20. //创建event_base,类似于epoll红黑树根节点
  21. struct event_base *base = event_base_new();
  22. /**
  23. * 创建事件
  24. * fd表示绑定到 创建的ev 上的文件描述符
  25. * EV_READ 一次读事件
  26. * EV_WRITE 一次写事件
  27. * EV_PERSIST 持续触发,需要结合event_base_dispatch使用,才生效.不指定,则只执行一次
  28. * read_cb满足事件监听的回调函数
  29. *
  30. * void read_cb(evutil_socket_t fd, short what, void *arg)
  31. * fd 对应这里的fd
  32. * what 对应这里的EV_READ | EV_PERSIST
  33. * arg 对应最后一个参数NULL
  34. */
  35. struct event *ev = event_new(base, fd, EV_READ | EV_PERSIST, read_cb, NULL);
  36. /**
  37. * 添加一个[常规事件]到event_base
  38. * timeout:设置超时时间
  39. * NULL:不会超时,等到事件被触发,回调函数立刻执行
  40. * 非0:期间检查事件有没有触发,一旦时间到则事件会被回调.
  41. */
  42. event_add(ev, NULL);
  43. /**
  44. * 从event_base删除事件
  45. *
  46. */
  47. //event_del(ev);
  48. //事件循环 可理解为while(1) epoll_wait()
  49. event_base_dispatch(base);
  50. //指定时间后停止
  51. // event_base_loopexit()
  52. //立即停止
  53. // event_base_loopbreak()
  54. //销毁添加的事件
  55. event_free(ev);
  56. //销毁event_base
  57. event_base_free(base);
  58. close(fd);
  59. return 0;
  60. }

client

  1. #include <unistd.h>
  2. #include <string.h>
  3. #include <fcntl.h>
  4. #include <event2/event.h>
  5. void write_cb(evutil_socket_t fd, short what, void *arg) {
  6. char buf[1024] = "hello";
  7. static int num = 0;
  8. sprintf(buf, "hello world %d\n", num++);
  9. printf("%s", buf);
  10. write(fd, buf, strlen(buf) + 1);
  11. sleep(1);
  12. }
  13. int main() {
  14. int fd = open("myfifo", O_WRONLY | O_NONBLOCK);
  15. //创建event_base
  16. struct event_base *base = event_base_new();
  17. //创建事件
  18. struct event *ev = event_new(base, fd, EV_WRITE | EV_PERSIST, write_cb, NULL);
  19. //添加事件
  20. event_add(ev, NULL);
  21. //事件循环
  22. event_base_dispatch(base);
  23. //销毁添加的事件
  24. event_free(ev);
  25. //销毁event_base
  26. event_base_free(base);
  27. close(fd);
  28. return 0;
  29. }

缓冲事件

server

  1. #include <sys/stat.h>
  2. #include <string.h>
  3. #include<event2/bufferevent.h>
  4. #include <event2/event.h>
  5. #include <event2/listener.h>
  6. #define PORT 8080
  7. /**
  8. * 缓冲事件
  9. * 有2个缓冲区,队列实现.
  10. */
  11. void read_cb(struct bufferevent *bev, void *ctx) {
  12. char buf[1024];
  13. //从读缓存中读取数据
  14. bufferevent_read(bev, buf, sizeof(buf));
  15. printf("client say : %s \n", buf);
  16. char *p = "world";
  17. //向写缓存中写数据,一旦有数据就会自动刷新,发送给对端,发送成功后,会被通知写回调方法.
  18. bufferevent_write(bev, p, strlen(p) + 1);
  19. }
  20. void write_cb(struct bufferevent *bev, void *ctx) {
  21. printf("发送成功 \n");
  22. }
  23. /**
  24. * 事件回调
  25. * @param bev
  26. *
  27. * @param what
  28. * 不同标志位,表示不同事件
  29. BEV_EVENT_READING 读缓冲区满足,则产生事件
  30. BEV_EVENT_WRITING 写缓冲区满足,则产生事件
  31. BEV_EVENT_EOF 读到文件结尾
  32. BEV_EVENT_ERROR 出错,则产生事件
  33. BEV_EVENT_TIMEOUT 超时
  34. BEV_EVENT_CONNECTED 请求的连接过程完成,客户端时可用
  35. *
  36. * @param ctx 回调函数参数
  37. */
  38. void event_cb(struct bufferevent *bev, short what, void *ctx) {
  39. if (what & BEV_EVENT_EOF) {
  40. printf("connection closed \n");
  41. } else if (what & BEV_EVENT_ERROR) {
  42. printf("error \n");
  43. }
  44. bufferevent_free(bev);
  45. printf("资源释放 \n");
  46. }
  47. /**
  48. * 客户端连接后,回调
  49. * @param listener 当调用evconnlistener_new_bind返回的监听器
  50. * @param fd 客户端的套接字
  51. * @param addr 客户端地址
  52. * @param len 客户端地址长度
  53. * @param ptr 当调用evconnlistener_new_bind设置的参数
  54. */
  55. void cb_listener(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int len, void *ptr) {
  56. struct event_base *base = (struct event_base *) ptr;
  57. /**
  58. * 创建bufferevent
  59. * struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options);
  60. * base event_base_new()返回值
  61. * fd 跟bufferevent绑定的fd
  62. * options
  63. * BEV_OPT_CLOSE_ON_FREE:释放bufferevent时关闭底层传输端口,也就是关闭底层套接字,释放底层bufferevent等
  64. */
  65. struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
  66. // bufferevent_free() 释放缓冲事件
  67. /**
  68. * 给bufferevent设置回调
  69. void bufferevent_setcb(struct bufferevent *bufev,
  70. bufferevent_data_cb readcb, bufferevent_data_cb writecb,
  71. bufferevent_event_cb eventcb, void *cbarg);
  72. bufev : bufferevent_socket_new返回值
  73. readcb :读回调,不用传NULL即可
  74. writecb :写事件满足时回调
  75. eventcb :事件回调
  76. cbarg :回调函数所有参数
  77. *
  78. */
  79. bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
  80. /**
  81. * 启用缓冲区
  82. * 默认写缓冲是启用的,读缓冲没启用
  83. */
  84. bufferevent_enable(bev, EV_READ);
  85. //禁用缓冲区
  86. // bufferevent_disable(bev, EV_READ);
  87. //获取缓冲区禁用状态,可通过&判断
  88. // bufferevent_get_enabled(bev);
  89. }
  90. int main() {
  91. struct sockaddr_in serv_addr;
  92. memset(&serv_addr, 0, sizeof(serv_addr));
  93. serv_addr.sin_family = AF_INET;
  94. serv_addr.sin_port = htons(PORT);
  95. serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  96. struct event_base *base = event_base_new();
  97. /**
  98. * 相当于socket,bind,listen,accept
  99. * 创建套接字,绑定,接收连接请求
  100. * struct evconnlistener *evconnlistener_new_bind(struct event_base *base,
  101. evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
  102. const struct sockaddr *sa, int socklen);
  103. * base : event_base_new()返回值
  104. * cb : 接受连接之后,回调函数
  105. * ptr : 回调函数参数
  106. * flags :
  107. * LEV_OPT_CLOSE_ON_FREE 释放bufferevent时关闭底层传输端口,也就是关闭底层套接字,释放底层bufferevent等
  108. * LEV_OPT_REUSEABLE 端口复用
  109. * backlog : listen的第二个参数, -1表示默认最大值
  110. * sa / socklen : 传给bind的参数 服务器的ip+port 以及长度
  111. */
  112. struct evconnlistener *listener = evconnlistener_new_bind(base, cb_listener, base,
  113. LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 36,
  114. (struct sockaddr *) &serv_addr, sizeof(serv_addr));
  115. event_base_dispatch(base);
  116. evconnlistener_free(listener);
  117. event_base_free(base);
  118. return 0;
  119. }

client

  1. #include <string.h>
  2. #include<event2/bufferevent.h>
  3. #include <event2/event.h>
  4. #include <arpa/inet.h>
  5. #include <unistd.h>
  6. #define PORT 8080
  7. void read_cb(struct bufferevent *bev, void *ctx) {
  8. char buf[1024];
  9. bufferevent_read(bev, buf, sizeof(buf));
  10. printf("server say : %s \n", buf);
  11. bufferevent_write(bev, buf, strlen(buf) + 1);
  12. sleep(1);
  13. }
  14. void write_cb(struct bufferevent *bev, void *ctx) {
  15. printf("发送成功 \n");
  16. }
  17. void event_cb(struct bufferevent *bev, short what, void *ctx) {
  18. if (what & BEV_EVENT_EOF) {
  19. printf("connection closed \n");
  20. } else if (what & BEV_EVENT_ERROR) {
  21. printf("error \n");
  22. } else if (what & BEV_EVENT_CONNECTED) {
  23. printf("已经连接服务器 \n");
  24. return;
  25. }
  26. bufferevent_free(bev);
  27. printf("资源释放 \n");
  28. }
  29. void read_terminal(evutil_socket_t fd, short what, void *arg) {
  30. char buf[1024] = {
  31. 0};
  32. int len = read(fd, buf, sizeof(buf));
  33. struct bufferevent *bev = (struct bufferevent *) arg;
  34. printf("terminal rev : %s \n", buf);
  35. bufferevent_write(bev, buf, len + 1);
  36. }
  37. int main() {
  38. struct sockaddr_in serv_addr;
  39. memset(&serv_addr, 0, sizeof(serv_addr));
  40. serv_addr.sin_family = AF_INET;
  41. serv_addr.sin_port = htons(PORT);
  42. inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
  43. int fd = socket(AF_INET, SOCK_STREAM, 0);
  44. struct event_base *base = event_base_new();
  45. struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
  46. /**
  47. * int bufferevent_socket_connect(struct bufferevent *bufferevent, struct sockaddr * addr, int len);
  48. * bufferevent 事件对象(封装了fd)
  49. * addr / len 等同于connect的addr和len参数
  50. */
  51. bufferevent_socket_connect(bev, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
  52. bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
  53. bufferevent_enable(bev, EV_READ);
  54. struct event *ev = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST, read_terminal, bev);
  55. event_add(ev, NULL);
  56. event_base_dispatch(base);
  57. event_free(ev);
  58. event_base_free(base);
  59. return 0;
  60. }

发表评论

表情:
评论列表 (有 0 条评论,286人围观)

还没有评论,来说两句吧...

相关阅读

    相关 libevent简述

    一。libevent概念 Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级

    相关 libevent

    简介: Libevent 是一个用[C语言][C][编写][Link 1]的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能

    相关 libevent介绍

      libevent讲解  什么是libevent libevent 是一个轻量级的事件触发的网络库。它适用于windows、linux、bsd等多种平台,它是跨平台

    相关 libevent入门

    花了两天的时间在libevent上,想总结下,就以写简单tutorial的方式吧,貌似没有一篇简单的说明,让人马上就能上手用的。 首先给出官方文档吧: [http: