一個簡易的echo server,使用了bufferevent。
Bufferevent
Bufferevents are higher level than evbuffers: each has an underlying evbuffer for reading and one for writing, and callbacks that are invoked under certain circumstances.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <event.h>
#include <event2/listener.h>
#define SVR_IP "127.0.0.1"
#define SVR_PORT 10000
#define BUFF_SIZE 1024
static void read_cb(struct bufferevent *bev, void *ctx) {
char buff[BUFF_SIZE];
int len;
memset(buff, 0, sizeof(buff));
/* Read data */
len = bufferevent_read(bev, buff, sizeof(buff));
printf("read: len=[%d] data=[%s]\n", len, buff);
/* Write data */
bufferevent_write(bev, buff, len);
}
static void write_cb(struct bufferevent *bev, void *ctx) {
printf("write finished\n");
}
static void event_cb(struct bufferevent *bev, short events, void *ctx) {
if (events & BEV_EVENT_EOF) {
printf("client disconnect\n");
bufferevent_free(bev);
} else if (events & BEV_EVENT_TIMEOUT) {
printf("client timeout\n");
bufferevent_free(bev);
} else {
/* Other case, maybe error occur */
bufferevent_free(bev);
}
}
static void accept_cb(struct evconnlistener *lev, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *ctx) {
struct event_base *evbase = ctx;
struct bufferevent *bev;
struct timeval tv;
printf("client connect from [%s:%u] over fd [%d]\n",
inet_ntoa(((struct sockaddr_in *) sa)->sin_addr),
(unsigned short) ntohs(((struct sockaddr_in *) sa)->sin_port), fd);
/* Create socket-based buffer event */
bev = bufferevent_socket_new(evbase, fd, BEV_OPT_CLOSE_ON_FREE);
if (bev == NULL) {
printf("bufferevent_socket_new() failed\n");
evutil_closesocket(fd);
return;
}
/* Set up callback function */
bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
/* Set up timeout for data read */
tv.tv_sec = 5;
tv.tv_usec = 0;
bufferevent_set_timeouts(bev, &tv, NULL);
/* Enable read event */
bufferevent_enable(bev, EV_READ);
}
int main(void) {
struct event_base *evbase;
struct sockaddr_in sin;
struct evconnlistener *lev;
/* Initialize event base */
if ((evbase = event_base_new()) == NULL) {
printf("event_base_new() failed\n");
return -1;
}
/* Set up server address */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(SVR_IP);
sin.sin_port = htons(SVR_PORT);
/* Bind socket */
lev = evconnlistener_new_bind(evbase, accept_cb, evbase,
LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
(struct sockaddr *) &sin, sizeof(sin));
if (lev == NULL) {
printf("bind() failed\n");
return -1;
} else {
printf("bind to [%s:%u] successfully\n", SVR_IP, SVR_PORT);
}
/* Enter event loop */
event_base_dispatch(evbase);
return 0;
}
編譯 (指定library path)
gcc -g -Wall -o server server.c -levent -I/opt/libevent-2.0.10-stable/include/ -L/opt/libevent-2.0.10-stable/lib/