On Mon, May 18, 2009 at 05:26:04PM +0200, q6Yr7e0o nIJDVMjC wrote:
Hi,
can somebody guide me how to write a simple echo server using libevent 2.0?
I've read into the sources of libevent (especially http.c) because i wanted
to know how to bind to a socket, accept new connections and read/write async
to the network.
But there are so many interal functions (like bind_socket bind_socket_ai)
which i have to copy (?) in order to bind to a socket that i think i got
something wrong.
I wouldn't look to http.c for examples; it was originally written for
a much older version of the API, and though it has been updated since
then, there are still a fair number of new interfaces that it isn't
using yet.
For one example of how to use the 2.0.1-alpha API, you could have a
look at chapter 1 of
http://www.wangafu.net/~nickm/libevent-book/ .
That's still a pretty ungainly way to do a server, though. In
2.0.2-alpha, there will be a new evconnlistener API to wrap most of
the busywork of listening for new connections. I've attacked a quick
echo server written with it to this email. [It works for me on Linux;
haven't tested it anywhere else.]
I hope we can get Libevent 2.0.2-alpha released this week. Until
then, you can use subversion to fetch the latest code from the
repository at
https://levent.svn.sourceforge.net/svnroot/levent/trunk/libevent
yrs,
--
Nick
#include event2/listener.h
#include event2/bufferevent.h
#include event2/buffer.h
#include arpa/inet.h
#include string.h
#include stdlib.h
#include stdio.h
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);
/* Copy all the data from the input buffer to the output buffer. */
evbuffer_add_buffer(output, input);
}
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);
}
}
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);
}
int
main(int argc, char **argv)
{
struct event_base *base;
struct evconnlistener *listener;
struct sockaddr_in sin;
int port = 9876;
if (argc 1) {
port = atoi(argv[1]);
}
if (port=0 || port65535) {
puts(Invalid port);
return 1;
}
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));
/* This is an INET address */
sin.sin_family = AF_INET;
/* Listen on 0.0.0.0 */
sin.sin_addr.s_addr = htonl(0);
/* Listen on the given port. */
sin.sin_port = htons(port);
listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
(struct sockaddr*)sin, sizeof(sin));
if (!listener) {
perror(Couldn't create listener);
return 1;
}
event_base_dispatch(base);
return 0;
}
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users