|
1 /* |
|
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. |
|
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; |
|
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 |
|
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 |
|
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 |
|
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; |
|
93 struct bufferevent *bev; |
|
94 |
|
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)); |
|
106 } |
|
107 |
|
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); |
|
141 } |