Last active
May 14, 2018 06:17
-
-
Save moccos/09d724930558d5c140b9 to your computer and use it in GitHub Desktop.
Modified libevent / sample / hello-world.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This exmple program provides a trivial server program that listens for TCP | |
connections on port 9995. When they arrive, it writes a short message to | |
each client connection, and closes each connection once it is flushed. | |
Where possible, it exits cleanly in response to a SIGINT (ctrl-c). | |
*/ | |
#include <string.h> | |
#include <errno.h> | |
#include <stdio.h> | |
#include <signal.h> | |
#include <stdlib.h> | |
#ifndef _WIN32 | |
#include <netinet/in.h> | |
# ifdef _XOPEN_SOURCE_EXTENDED | |
# include <arpa/inet.h> | |
# endif | |
#include <sys/socket.h> | |
#endif | |
#include <event2/bufferevent.h> | |
#include <event2/buffer.h> | |
#include <event2/listener.h> | |
#include <event2/util.h> | |
#include <event2/event.h> | |
#include <algorithm> | |
static const char MESSAGE[] = "Hello, World!\n"; | |
static const int PORT = 9995; | |
static void listener_cb(struct evconnlistener *, evutil_socket_t, | |
struct sockaddr *, int socklen, void *); | |
static void conn_readcb(struct bufferevent *, void *); | |
static void conn_writecb(struct bufferevent *, void *); | |
static void conn_eventcb(struct bufferevent *, short, void *); | |
static void signal_cb(evutil_socket_t, short, void *); | |
int | |
main(int argc, char **argv) | |
{ | |
struct event_base *base; | |
struct evconnlistener *listener; | |
struct event *signal_event; | |
struct sockaddr_in sin; | |
#ifdef _WIN32 | |
WSADATA wsa_data; | |
WSAStartup(0x0201, &wsa_data); | |
#endif | |
base = event_base_new(); | |
if (!base) { | |
fprintf(stderr, "Could not initialize libevent!\n"); | |
return 1; | |
} | |
memset(&sin, 0, sizeof(sin)); | |
sin.sin_family = AF_INET; | |
sin.sin_port = htons(PORT); | |
listener = evconnlistener_new_bind(base, listener_cb, (void *)base, | |
LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, | |
(struct sockaddr*)&sin, | |
sizeof(sin)); | |
if (!listener) { | |
fprintf(stderr, "Could not create a listener!\n"); | |
return 1; | |
} | |
signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base); | |
if (!signal_event || event_add(signal_event, NULL)<0) { | |
fprintf(stderr, "Could not create/add a signal event!\n"); | |
return 1; | |
} | |
event_base_dispatch(base); | |
evconnlistener_free(listener); | |
event_free(signal_event); | |
event_base_free(base); | |
printf("done\n"); | |
return 0; | |
} | |
static void | |
listener_cb(struct evconnlistener *listener, evutil_socket_t fd, | |
struct sockaddr *sa, int socklen, void *user_data) | |
{ | |
struct event_base *base = (struct event_base*)user_data; | |
struct bufferevent *bev; | |
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); | |
if (!bev) { | |
fprintf(stderr, "Error constructing bufferevent!"); | |
event_base_loopbreak(base); | |
return; | |
} | |
bufferevent_setcb(bev, conn_readcb, conn_writecb, conn_eventcb, nullptr); | |
printf("listener_cb\n"); | |
bufferevent_enable(bev, EV_READ); | |
//bufferevent_enable(bev, EV_WRITE); | |
//bufferevent_disable(bev, EV_READ); | |
//bufferevent_write(bev, MESSAGE, strlen(MESSAGE)); | |
} | |
static void | |
conn_readcb(struct bufferevent *bev, void *user_data) | |
{ | |
struct evbuffer *input = bufferevent_get_input(bev); | |
auto len = evbuffer_get_length(input); | |
printf("conn_readcb: len %lu\n", len); | |
char *buf = (char*)malloc(len); | |
evbuffer_copyout(input, buf, len); | |
for (auto i = 0; i < std::min((int)len, 4); ++i) { | |
printf("%02x ", buf[i]); | |
} | |
printf("\n"); | |
evbuffer_drain(input, len); | |
} | |
static void | |
conn_writecb(struct bufferevent *bev, void *user_data) | |
{ | |
printf("conn_writecb\n"); | |
struct evbuffer *output = bufferevent_get_output(bev); | |
if (evbuffer_get_length(output) == 0) { | |
printf("flushed answer\n"); | |
bufferevent_free(bev); | |
} | |
} | |
static void | |
conn_eventcb(struct bufferevent *bev, short events, void *user_data) | |
{ | |
printf("conn_eventcb\n"); | |
if (events & BEV_EVENT_EOF) { | |
printf("Connection closed.\n"); | |
} else if (events & BEV_EVENT_ERROR) { | |
printf("Got an error on the connection: %s\n", | |
strerror(errno));/*XXX win32*/ | |
} | |
/* None of the other events can happen here, since we haven't enabled | |
* timeouts */ | |
bufferevent_free(bev); | |
} | |
static void | |
signal_cb(evutil_socket_t sig, short events, void *user_data) | |
{ | |
struct event_base *base = (struct event_base*)user_data; | |
struct timeval delay = { 2, 0 }; | |
printf("Caught an interrupt signal; exiting cleanly in two seconds.\n"); | |
event_base_loopexit(base, &delay); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% telnet localhost 9995 | |
Trying 127.0.0.1... | |
Connected to localhost. | |
Escape character is '^]'. | |
asdf | |
^T^@ | |
Connection closed by foreign host. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% ./ev_test | |
listener_cb | |
conn_readcb: len 6 | |
61 73 64 66 | |
conn_readcb: len 4 | |
14 00 0d 0a | |
conn_readcb: len 2 | |
0d 0a | |
^CCaught an interrupt signal; exiting cleanly in two seconds. | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment