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 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 int 39 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 = {0}; 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 sin.sin_family = AF_INET; 58 sin.sin_port = htons(PORT); 59 60 listener = evconnlistener_new_bind(base, listener_cb, (void *)base, 61 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, 62 (struct sockaddr*)&sin, 63 sizeof(sin)); 64 65 if (!listener) { 66 fprintf(stderr, "Could not create a listener!\n"); 67 return 1; 68 } 69 70 signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base); 71 72 if (!signal_event || event_add(signal_event, NULL)<0) { 73 fprintf(stderr, "Could not create/add a signal event!\n"); 74 return 1; 75 } 76 77 event_base_dispatch(base); 78 79 evconnlistener_free(listener); 80 event_free(signal_event); 81 event_base_free(base); 82 83 printf("done\n"); 84 return 0; 85 } 86 87 static void 88 listener_cb(struct evconnlistener *listener, evutil_socket_t fd, 89 struct sockaddr *sa, int socklen, void *user_data) 90 { 91 struct event_base *base = user_data; 92 struct bufferevent *bev; 93 94 bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); 95 if (!bev) { 96 fprintf(stderr, "Error constructing bufferevent!"); 97 event_base_loopbreak(base); 98 return; 99 } 100 bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL); 101 bufferevent_enable(bev, EV_WRITE); 102 bufferevent_disable(bev, EV_READ); 103 104 bufferevent_write(bev, MESSAGE, strlen(MESSAGE)); 105 } 106 107 static void 108 conn_writecb(struct bufferevent *bev, void *user_data) 109 { 110 struct evbuffer *output = bufferevent_get_output(bev); 111 if (evbuffer_get_length(output) == 0) { 112 printf("flushed answer\n"); 113 bufferevent_free(bev); 114 } 115 } 116 117 static void 118 conn_eventcb(struct bufferevent *bev, short events, void *user_data) 119 { 120 if (events & BEV_EVENT_EOF) { 121 printf("Connection closed.\n"); 122 } else if (events & BEV_EVENT_ERROR) { 123 printf("Got an error on the connection: %s\n", 124 strerror(errno));/*XXX win32*/ 125 } 126 /* None of the other events can happen here, since we haven't enabled 127 * timeouts */ 128 bufferevent_free(bev); 129 } 130 131 static void 132 signal_cb(evutil_socket_t sig, short events, void *user_data) 133 { 134 struct event_base *base = user_data; 135 struct timeval delay = { 2, 0 }; 136 137 printf("Caught an interrupt signal; exiting cleanly in two seconds.\n"); 138 139 event_base_loopexit(base, &delay); 140 } 141