2 This exmple 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.
6 Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
15 #include <netinet/in.h>
16 # ifdef _XOPEN_SOURCE_EXTENDED
17 # include <arpa/inet.h>
19 #include <sys/socket.h>
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>
28 static const char MESSAGE
[] = "Hello, World!\n";
30 static const int PORT
= 9995;
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 *);
39 main(int argc
, char **argv
)
41 struct event_base
*base
;
42 struct evconnlistener
*listener
;
43 struct event
*signal_event
;
45 struct sockaddr_in sin
;
48 WSAStartup(0x0201, &wsa_data
);
51 base
= event_base_new();
53 fprintf(stderr
, "Could not initialize libevent!\n");
57 memset(&sin
, 0, sizeof(sin
));
58 sin
.sin_family
= AF_INET
;
59 sin
.sin_port
= htons(PORT
);
61 listener
= evconnlistener_new_bind(base
, listener_cb
, (void *)base
,
62 LEV_OPT_REUSEABLE
|LEV_OPT_CLOSE_ON_FREE
, -1,
63 (struct sockaddr
*)&sin
,
67 fprintf(stderr
, "Could not create a listener!\n");
71 signal_event
= evsignal_new(base
, SIGINT
, signal_cb
, (void *)base
);
73 if (!signal_event
|| event_add(signal_event
, NULL
)<0) {
74 fprintf(stderr
, "Could not create/add a signal event!\n");
78 event_base_dispatch(base
);
80 evconnlistener_free(listener
);
81 event_free(signal_event
);
82 event_base_free(base
);
89 listener_cb(struct evconnlistener
*listener
, evutil_socket_t fd
,
90 struct sockaddr
*sa
, int socklen
, void *user_data
)
92 struct event_base
*base
= user_data
;
93 struct bufferevent
*bev
;
95 bev
= bufferevent_socket_new(base
, fd
, BEV_OPT_CLOSE_ON_FREE
);
97 fprintf(stderr
, "Error constructing bufferevent!");
98 event_base_loopbreak(base
);
101 bufferevent_setcb(bev
, NULL
, conn_writecb
, conn_eventcb
, NULL
);
102 bufferevent_enable(bev
, EV_WRITE
);
103 bufferevent_disable(bev
, EV_READ
);
105 bufferevent_write(bev
, MESSAGE
, strlen(MESSAGE
));
109 conn_writecb(struct bufferevent
*bev
, void *user_data
)
111 struct evbuffer
*output
= bufferevent_get_output(bev
);
112 if (evbuffer_get_length(output
) == 0) {
113 printf("flushed answer\n");
114 bufferevent_free(bev
);
119 conn_eventcb(struct bufferevent
*bev
, short events
, void *user_data
)
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*/
127 /* None of the other events can happen here, since we haven't enabled
129 bufferevent_free(bev
);
133 signal_cb(evutil_socket_t sig
, short events
, void *user_data
)
135 struct event_base
*base
= user_data
;
136 struct timeval delay
= { 2, 0 };
138 printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
140 event_base_loopexit(base
, &delay
);