当前位置: 首页 > 图灵资讯 > 技术篇> libevent入门教程:Echo Server based on libevent

libevent入门教程:Echo Server based on libevent

来源:图灵教育
时间:2023-06-08 09:23:40

ent_set_timeouts(bev, struct timeval *READ, struct timeval *WRITE)设置读写超时, 处理error_cb中的超时。 *. read_cb和write_cb的原型是 void read_or_write_callback(struct bufferevent *bev, void *arg) error_cb的原型是 void error_cb(struct bufferevent *bev, short error, void *arg) ///这是event的标准回调函数原型 event__可以从bev中提取libevent的APIbase、sockfd、inputRTFM~/output等相关数据 所以代码简化到read_cb和read_cb,只需要几行error_cb函数即可:

void   read_cb(  struct   bufferevent *bev,     void   *arg) {          char   line[256];          int   n;      evutil_socket_t fd = bufferevent_getfd(bev);          while   (n = bufferevent_read(bev, line, 256), n > 0)          bufferevent_write(bev, line, n);  }  void   error_cb(  struct   bufferevent *bev,     short   event,     void   *arg) {      bufferevent_free(bev);  }

因此,echo支持大并发量 server成型了!下面附上无注释的echo server源码,110行,再抄几遍,就能完全理解!更复杂的例子见官方文档中的例子【Example: A simpler ROT13 server with Libevent】

include   <stdio.h>  #  include   <stdlib.h>  #  include   <errno.h>  #  include   <assert.h>  #  include   <event2/event.h>  #  include   <event2/bufferevent.h>  #  define   LISTEN_PORT 9999  #  define   LISTEN_BACKLOG 32  void   do_accept(evutil_socket_t listener,     short   event,     void   *arg);  void   read_cb(  struct   bufferevent *bev,     void   *arg);  void   error_cb(  struct   bufferevent *bev,     short   event,     void   *arg);  void   write_cb(  struct   bufferevent *bev,     void   *arg);  int   main(  int   argc,     char   *argv[])  {          int   ret;      evutil_socket_t listener;      listener = socket(AF_INET, SOCK_STREAM, 0);      assert(listener > 0);      evutil_make_listen_socket_reuseable(listener);          struct   sockaddr_in sin;      sin.sin_family = AF_INET;      sin.sin_addr.s_addr = 0;      sin.sin_port = htons(LISTEN_PORT);          if   (bind(listener, (  struct   sockaddr *)&sin,     sizeof(sin)) < 0) {          perror("bind");              return   1;      }          if   (listen(listener, LISTEN_BACKLOG) < 0) {          perror("listen");              return   1;      }          printf   ("Listening...\n");      evutil_make_socket_nonblocking(listener);          struct   event_base *base = event_base_new();      assert(base !=     NULL);          struct   event *listen_event;      listen_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (  void*)base);      event_add(listen_event,     NULL);      event_base_dispatch(base);          printf("The End.");          return   0;  }  void   do_accept(evutil_socket_t listener,     short   event,     void   *arg)  {          struct   event_base *base = (  struct   event_base *)arg;      evutil_socket_t fd;          struct   sockaddr_in sin;      socklen_t slen;      fd = accept(listener, (  struct   sockaddr *)&sin, &slen);          if   (fd < 0) {          perror("accept");              return;      }          if   (fd > FD_SETSIZE) {          perror("fd > FD_SETSIZE\n");              return;      }          printf("ACCEPT: fd = %u\n", fd);          struct   bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);      bufferevent_setcb(bev, read_cb,     NULL, error_cb, arg);      bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);  }  void   read_cb(  struct   bufferevent *bev,     void   *arg)  {  #  define   MAX_LINE    256          char   line[MAX_LINE+1];          int   n;      evutil_socket_t fd = bufferevent_getfd(bev);          while   (n = bufferevent_read(bev, line, MAX_LINE), n > 0) {          line[n] = '\0';              printf("fd=%u, read line: %s\n", fd, line);          bufferevent_write(bev, line, n);      }  }  void   write_cb(  struct   bufferevent *bev,     void   *arg) {}  void   error_cb(  struct   bufferevent *bev,     short   event,     void   *arg)  {      evutil_socket_t fd = bufferevent_getfd(bev);          printf("fd = %u, ", fd);          if   (event & BEV_EVENT_TIMEOUT) {              printf("Timed out\n"); //  if   bufferevent_set_timeouts() called      }          else     if   (event & BEV_EVENT_EOF) {              printf("connection closed\n");      }          else     if   (event & BEV_EVENT_ERROR) {              printf("some other error\n");      }      bufferevent_free(bev);  }