0
点赞
收藏
分享

微信扫一扫

libevent入门教程:Echo Server based on libevent


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的标准回调函数原型
      可以从bev中用libevent的API提取出event_base、sockfd、input/output等相关数据,详情RTFM~
    

    于是代码简化到只需要几行的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);
  
}

举报

相关推荐

0 条评论