1/*
  2   This example program provides a trivial server program that listens for TCP
  3   connections on port 9995.  When they arrive, it writes a short message to
  4   each client connection, and closes each connection once it is flushed.
  5 
  6   Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
  7 */
  8 
  9 
 10 #include <string.h>
 11 #include <errno.h>
 12 #include <stdio.h>
 13 #include <signal.h>
 14 #ifndef _WIN32
 15 #include <netinet/in.h>
 16 # ifdef _XOPEN_SOURCE_EXTENDED
 17 #  include <arpa/inet.h>
 18 # endif
 19 #include <sys/socket.h>
 20 #endif
 21  //使用libevent库的头文件
 22 #include <event2/bufferevent.h>
 23 #include <event2/buffer.h>
 24 #include <event2/listener.h>
 25 #include <event2/util.h>
 26 #include <event2/event.h>
 27 
 28 static const char MESSAGE[] = "Hello, World!\n";
 29 
 30 static const int PORT = 9995;
 31 //一些回调函数的声明,包括监听回调、写回调、事件回调、信号回调
 32 static void listener_cb(struct evconnlistener *, evutil_socket_t,
 33     struct sockaddr *, int socklen, void *);
 34 static void conn_writecb(struct bufferevent *, void *);
 35 static void conn_eventcb(struct bufferevent *, short, void *);
 36 static void signal_cb(evutil_socket_t, short, void *);
 37 
 38 
 39 int  main(int argc, char **argv)
 40 {   //事件基座的变量声明
 41     struct event_base *base;
 42     struct evconnlistener *listener;//监听器变量声明
 43     struct event *signal_event;//信号事件声明
 44 
 45     struct sockaddr_in sin;//服务器的地址声明
 46 #ifdef _WIN32
 47     WSADATA wsa_data;
 48     WSAStartup(0x0201, &wsa_data);
 49 #endif
 50 
 51     base = event_base_new(); //创建一个基底
 52     if (!base) {//出错处理
 53         fprintf(stderr, "Could not initialize libevent!\n");
 54         return 1;
 55     }
 56     //初始化服务器的地址结构
 57     memset(&sin, 0, sizeof(sin));
 58     sin.sin_family = AF_INET;
 59     sin.sin_port = htons(PORT);
 60     //创建一个监听器,用于监听客户端的连接请求,里面的listener_cb被回调说明有新的客户端来连接,产生一个新的fd
 61     listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
 62         LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
 63         (struct sockaddr*)&sin,
 64         sizeof(sin));
 65 
 66     if (!listener) {//出错处理
 67         fprintf(stderr, "Could not create a listener!\n");
 68         return 1;
 69     }
 70     //创建一个信号对象,当SIGINT信号产生,signal_cb会被回调
 71     signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
 72     //出错处理
 73     if (!signal_event || event_add(signal_event, NULL)<0) {
 74         fprintf(stderr, "Could not create/add a signal event!\n");
 75         return 1;
 76     }
 77     //启动循环监听
 78     event_base_dispatch(base);
 79     //释放资源
 80     evconnlistener_free(listener);
 81     event_free(signal_event);
 82     event_base_free(base);
 83 
 84     printf("done\n");
 85     return 0;
 86 }
 87 
 88 static void//参数依次是:监听器对象、新的fd、客户端的地址结构、地址结构长度、回调函数参数
 89 listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
 90     struct sockaddr *sa, int socklen, void *user_data)
 91 {
 92     struct event_base *base = user_data;   //通过参数将基底传递进来,创建bufferevent对象要用
 93     struct bufferevent *bev;
 94     //创建bufferevent事件对象,将新的fd封装在里面,事件对象有读缓冲、写缓冲
 95     bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
 96     if (!bev) {//出错处理
 97         fprintf(stderr, "Error constructing bufferevent!");
 98         event_base_loopbreak(base);
 99         return;
100     }
101     bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL);//给事件对象里面的写缓冲和事件缓冲设置回调
102     bufferevent_enable(bev, EV_WRITE);//设置为使能状态
103     bufferevent_disable(bev, EV_READ);
104 
105     bufferevent_write(bev, MESSAGE, strlen(MESSAGE));相当于write函数
106 }
107    //写回调函数的具体实现,参数依次是:事件对象、bufferevent_setcb()函数中的最后一个参数,本例子中设为NULL
108 static void
109 conn_writecb(struct bufferevent *bev, void *user_data)
110 {
111     struct evbuffer *output = bufferevent_get_output(bev);
112     if (evbuffer_get_length(output) == 0) {
113         printf("flushed answer\n");
114         bufferevent_free(bev);
115     }
116 }
117   //事件回调函数
118 static void
119 conn_eventcb(struct bufferevent *bev, short events, void *user_data)
120 {
121     if (events & BEV_EVENT_EOF) {//对端关闭
122         printf("Connection closed.\n");
123     } else if (events & BEV_EVENT_ERROR) {//出错
124         printf("Got an error on the connection: %s\n",
125             strerror(errno));/*XXX win32*/
126     }
127     /* None of the other events can happen here, since we haven't enabled
128      * timeouts */
129     bufferevent_free(bev);//释放事件对象
130 }
131   //信号回调
132 static void
133 signal_cb(evutil_socket_t sig, short events, void *user_data)
134 {
135     struct event_base *base = user_data;
136     struct timeval delay = { 2, 0 };//定时器
137 
138     printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
139 
140     event_base_loopexit(base, &delay);//2秒之后退出监听循环
141 }

 客户端:

服务器: