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 || port>65535) { 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