Created
November 7, 2016 11:45
-
-
Save GZShi/3c4e8a61f96b31a35203dd0650070d24 to your computer and use it in GitHub Desktop.
libevent example: echo server
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
#include <WinSock2.h> | |
#include <event.h> | |
#include <event2/listener.h> | |
#include <event2/util.h> | |
#include <iostream> | |
#include <thread> | |
#pragma comment(lib, "libevent.lib") | |
#pragma comment(lib, "libevent_core.lib") | |
#pragma comment(lib, "libevent_extras.lib") | |
#pragma comment (lib, "Ws2_32.lib") | |
#pragma comment (lib, "Mswsock.lib") | |
#pragma comment (lib, "AdvApi32.lib") | |
using namespace std; | |
static void echo_read_cb(struct bufferevent *bev, void *ctx) | |
{ | |
/* This callback is invoked when there is data to read on bev. */ | |
struct evbuffer *input = bufferevent_get_input(bev); | |
struct evbuffer *output = bufferevent_get_output(bev); | |
size_t len = evbuffer_get_length(input); | |
char *data; | |
data = (char*)malloc(len); | |
evbuffer_copyout(input, data, len); | |
printf("we got some data: %s\n", data); | |
/* Copy all the data from the input buffer to the output buffer. */ | |
evbuffer_add_buffer(output, input); | |
free(data); | |
} | |
static void echo_event_cb(struct bufferevent *bev, short events, void *ctx) | |
{ | |
if (events & BEV_EVENT_ERROR) | |
perror("Error from bufferevent"); | |
if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { | |
bufferevent_free(bev); | |
} | |
} | |
void bufferevent_getcb(struct bufferevent *bufev, | |
bufferevent_data_cb *readcb_ptr, | |
bufferevent_data_cb *writecb_ptr, | |
bufferevent_event_cb *eventcb_ptr, | |
void **cbarg_ptr); | |
static void | |
accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx) | |
{ | |
/* We got a new connection! Set up a bufferevent for it. */ | |
struct event_base *base = evconnlistener_get_base(listener); | |
struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); | |
bufferevent_setcb(bev, echo_read_cb, NULL, echo_event_cb, NULL); | |
bufferevent_enable(bev, EV_READ | EV_WRITE); | |
} | |
static void accept_error_cb(struct evconnlistener *listener, void *ctx) | |
{ | |
struct event_base *base = evconnlistener_get_base(listener); | |
int err = EVUTIL_SOCKET_ERROR(); | |
fprintf(stderr, "Got an error %d (%s) on the listener. " | |
"Shutting down.\n", err, evutil_socket_error_to_string(err)); | |
event_base_loopexit(base, NULL); | |
} | |
int main(int argc, char **argv) | |
{ | |
struct event_base *base; | |
struct evconnlistener *listener; | |
struct sockaddr_in sin; | |
WSADATA wsaData; | |
auto opt = MAKEWORD(2, 1); | |
WSAStartup(opt, &wsaData); | |
/* Create new event base */ | |
base = event_base_new(); | |
if (!base) { | |
puts("Couldn't open event base"); | |
return 1; | |
} | |
/* Clear the sockaddr before using it, in case there are extra | |
* platform-specific fields that can mess us up. */ | |
memset(&sin, 0, sizeof(sin)); | |
sin.sin_family = AF_INET; | |
sin.sin_port = htons(30001); | |
/* Create a new listener */ | |
listener = evconnlistener_new_bind(base, accept_conn_cb, (void*)base, | |
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, | |
(struct sockaddr *) &sin, sizeof(sin)); | |
if (!listener) { | |
perror("Couldn't create listener"); | |
return 1; | |
} | |
evconnlistener_set_error_cb(listener, accept_error_cb); | |
/* Lets rock */ | |
event_base_dispatch(base); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment