echo server

1.The libevent API provides a mechanism[机制] to execute a callback function when a specific event occurs on a file descriptor or after a timeout has been reached. Furthermore, libevent also support callbacks due to signals or regular timeouts.

//支持I/O 信号 定时器

2.libevent supports /dev/poll, kqueue(2), event ports, POSIX select(2), Windows select(), poll(2), and epoll(4).

3.Libevent can also be used for multi-threaded applications, either by isolating[孤立] each event_base so that only a single thread accesses it, or by locked access to a single shared event_base. 

//默认单线程,也可以用于多线程(一个线程一个event_base,或者加锁)。

跨平台、异步事件驱动:ACE_Reactor好像也是事件驱动、Reactor模式

// echo server.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 

void do_accept(evutil_socket_t listener, short event, void *arg);
void read_cb(struct bufferevent *bev, void *arg);
void error_cb(struct bufferevent *bev, short event, void *arg);
void write_cb(struct bufferevent *bev, void *arg);

int _tmain(int argc, _TCHAR* argv[])
{
	int ret = 0;

#ifdef WIN32  
	WSADATA wsa_data;  
	WSAStartup(0x0201, &wsa_data);  
#endif

	evutil_socket_t lsocket;
	lsocket = socket(AF_INET,SOCK_STREAM,0);

	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_addr.S_un.S_addr = 0;
	sin.sin_port = htons(8889);

	if(bind(lsocket,(struct sockaddr*)&sin,sizeof(sin)) < 0)
	{
		perror("bind");
		return -1;
	}

	if(listen(lsocket,10) < 0)
	{
		perror("listen");
		return -1;
	}

	struct event_base *base = event_base_new();
	struct event* listen_event;
	listen_event = event_new(base,lsocket,EV_READ|EV_PERSIST,do_accept,(void*)base);
	event_add(listen_event,NULL);
	event_base_dispatch(base);

	return 0;
}

void do_accept(evutil_socket_t tsocket,short event,void *arg)
{
	typedef int socklen_t;
	struct event_base *base = (struct event_base*)arg;
	struct sockaddr_in sin;
	socklen_t slen = sizeof(sin);
	evutil_socket_t fd = accept(tsocket,(struct sockaddr*)&sin,&slen);
	if(fd < 0)
	{
		perror("accept");
		return;
	}

	struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
	bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);
	bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);
}

void read_cb(struct bufferevent *bev, void *arg)
{
#define MAX_LINE    256
	char line[MAX_LINE+1];
	evutil_socket_t fd = bufferevent_getfd(bev);

	int n = 0;
	while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) 
	{
		line[n] = '\0';
		printf("fd=%u, read line: %s\n", fd, line);
		bufferevent_write(bev, line, n);
	}
}

void write_cb(struct bufferevent *bev, void *arg) 
{
}

void error_cb(struct bufferevent *bev, short event, void *arg)
{
	evutil_socket_t fd = bufferevent_getfd(bev);
	printf("fd = %u, ", fd);
	if (event & BEV_EVENT_TIMEOUT) 
	{
		printf("Timed out\n"); //if bufferevent_set_timeouts() called
	}
	else if (event & BEV_EVENT_EOF) 
	{
		printf("connection closed\n");
	}
	else if (event & BEV_EVENT_ERROR) 
	{
		printf("some other error\n");
	}
	bufferevent_free(bev);

  evutil_socket_t:在除Windows之外的大多数地方,套接字是个整数,操作系统按照数值次序进行处理。然而,使用Windows套接字API时,socket类型为SOCKET(句柄),收到这个句柄的次序是未定义的。所以,在Windows中,libevent定义evutil_socket_t类型为整型指针,可以处理socket()或者accept()的输出,而没有指针截断的风险,如以下宏:

#ifdef WIN32
#define evutil_socket_t intptr_t
#else
#define evutil_socket_t int
#endif
echo代码来自网络


你可能感兴趣的:(libevent)