ent_set_timeouts(bev, struct timeval *READ, struct timeval *WRITE)来设置读写超时, 在error_cb里面处理超时。
*. read_cb和write_cb的原型是
void read_or_write_callback(struct bufferevent *bev, void *arg)
error_cb的原型是
void error_cb(struct bufferevent *bev, short error, void *arg) //这个是event的标准回调函数原型
可以从bev中用libevent的API提取出event_base、sockfd、input/output等相关数据,详情RTFM~
于是代码简化到只需要几行的read_cb和error_cb函数即可:
void read_cb(struct bufferevent *bev, void *arg) {
char line[256];
int n;
evutil_socket_t fd = bufferevent_getfd(bev);
while (n = bufferevent_read(bev, line, 256), n > 0)
bufferevent_write(bev, line, n);
}
void error_cb(struct bufferevent *bev, short event, void *arg) {
bufferevent_free(bev);
}
char line[256];
int n;
evutil_socket_t fd = bufferevent_getfd(bev);
while (n = bufferevent_read(bev, line, 256), n > 0)
bufferevent_write(bev, line, n);
}
void error_cb(struct bufferevent *bev, short event, void *arg) {
bufferevent_free(bev);
}
于是一个支持大并发量的echo server就成型了!下面附上无注释的echo server源码,110行,多抄几遍,就能完全弄懂啦!更复杂的例子参见官方文档里面的【Example: A simpler ROT13 server with Libevent】
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#define LISTEN_PORT 9999
#define LISTEN_BACKLOG 32
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 main(int argc, char *argv[])
{
int ret;
evutil_socket_t listener;
listener = socket(AF_INET, SOCK_STREAM, 0);
assert(listener > 0);
evutil_make_listen_socket_reuseable(listener);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(LISTEN_PORT);
if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("bind");
return 1;
}
if (listen(listener, LISTEN_BACKLOG) < 0) {
perror("listen");
return 1;
}
printf ("Listening...\n");
evutil_make_socket_nonblocking(listener);
struct event_base *base = event_base_new();
assert(base != NULL);
struct event *listen_event;
listen_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);
event_add(listen_event, NULL);
event_base_dispatch(base);
printf("The End.");
return 0;
}
void do_accept(evutil_socket_t listener, short event, void *arg)
{
struct event_base *base = (struct event_base *)arg;
evutil_socket_t fd;
struct sockaddr_in sin;
socklen_t slen;
fd = accept(listener, (struct sockaddr *)&sin, &slen);
if (fd < 0) {
perror("accept");
return;
}
if (fd > FD_SETSIZE) {
perror("fd > FD_SETSIZE\n");
return;
}
printf("ACCEPT: fd = %u\n", fd);
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];
int n;
evutil_socket_t fd = bufferevent_getfd(bev);
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);
}
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#define LISTEN_PORT 9999
#define LISTEN_BACKLOG 32
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 main(int argc, char *argv[])
{
int ret;
evutil_socket_t listener;
listener = socket(AF_INET, SOCK_STREAM, 0);
assert(listener > 0);
evutil_make_listen_socket_reuseable(listener);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(LISTEN_PORT);
if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("bind");
return 1;
}
if (listen(listener, LISTEN_BACKLOG) < 0) {
perror("listen");
return 1;
}
printf ("Listening...\n");
evutil_make_socket_nonblocking(listener);
struct event_base *base = event_base_new();
assert(base != NULL);
struct event *listen_event;
listen_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);
event_add(listen_event, NULL);
event_base_dispatch(base);
printf("The End.");
return 0;
}
void do_accept(evutil_socket_t listener, short event, void *arg)
{
struct event_base *base = (struct event_base *)arg;
evutil_socket_t fd;
struct sockaddr_in sin;
socklen_t slen;
fd = accept(listener, (struct sockaddr *)&sin, &slen);
if (fd < 0) {
perror("accept");
return;
}
if (fd > FD_SETSIZE) {
perror("fd > FD_SETSIZE\n");
return;
}
printf("ACCEPT: fd = %u\n", fd);
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];
int n;
evutil_socket_t fd = bufferevent_getfd(bev);
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);
}
相关推荐
libevent example. echo server. use c++11 gcc 4.8.5 thread_pool singleton , io thread , servant thread layer
《学习libevent入门电子书》是一本针对libevent这一开源事件库的学习资料,它对于深入理解和使用libevent具有极大的价值。libevent是一个高度可移植的库,它为编写高性能、异步网络应用提供了基础。在现代软件开发,...
在项目中,`libevent-client`和`libevent-server`分别代表了客户端和服务器的源代码文件,包含了上述过程的实现细节。通过阅读和分析这些代码,可以更深入地理解libevent在UDP relay场景中的应用。
使用 libevent 可以快速构建一个 Echo Server。首先,创建一个 event_base,用于管理和调度事件。然后,创建一个监听事件,并将其绑定到 event_base 上。当有连接请求时,回调函数会被触发,处理请求并返回响应。 7...
附件为本人整理的libevent的入门学习资料,时候零基础学习。
在提供的工程文件中,`tcp_server.sln`是Visual Studio的解决方案文件,`tcp_server.v11.suo`是用户设置文件,`Debug`目录包含编译后的可执行文件和中间文件,`libevent`目录可能包含了libevent库的头文件和库文件。...
cd sample mkdir htdocs vim htdocs/index.html ./http-server -p 18080 -v htdocs curl -i http://127.0.0.1:18080/index.html
"libevent_webservice:基于libevent的简单异步多线程Webservice" 这个标题提到了两个关键概念:libevent和异步多线程Webservice。Libevent是一个开源库,用于处理事件通知,尤其适用于编写高性能、可扩展的网络...
"evpp based echo server" 是一个基于qihoo360公司开源的网络框架EVPP构建的简单回显服务器。EVPP(Efficient Vector Protocol Processor)是一个高性能、异步事件驱动的C++网络库,设计用于开发高并发、低延迟的...
在"libevent demo"中,我们通常会看到一个基础的echoserver示例,它是使用libevent来实现的。Echoserver是一个简单的服务器,它接收客户端发送的数据并原样返回,常用于测试网络连接和数据传输。 **Libevent核心...
Multithreaded, libevent-based socket server. http://sourceforge.net/p/libevent-thread/code/ci/master/tree/README
libevent,多线程,client,serverlibevent多线程, 参考mariotcp 参考http://blog.csdn.net/i_am_jojo/article/details/7587838流程图
Name : libevent-devel Version : 1.4.13 Vendor : StartCom Ltd_, http://www_startcom_org Release : 1 Date : 2010-04-07 22:14:06 Group : Development/Libraries Source RPM : libevent-1.4.13-1.src.rpm ...
openwrt-libevent21 用于 openwrt 的 libevent 2.1 包为目标平台快速构建包: 从获取相应的预构建 OpenWrt SDK(例如针对 ar71xx 平台的) 交叉编译- 需要将工具链二进制文件添加到PATH环境变量并定义STAGING_DIR 。...
《libevent-1.4.15源码阅读注释》是针对libevent库的一个详细解析,这个开源项目为系统编程提供了强大的事件通知机制。libevent是一个轻量级的库,它允许程序员以统一的方式处理各种事件,如网络连接、定时器以及...
本文将深入探讨如何在多线程环境中使用Libevent进行事件处理,并分享一个基于Libevent的多线程实现案例。 首先,理解Libevent的核心机制至关重要。Libevent提供了一个事件基础结构,它能够将来自不同来源的事件(如...
**libevent服务器与客户端详解** libevent是一个高度可移植、高性能的事件通知库,它能够帮助程序员编写出高效的网络服务程序。在这个项目中,我们实现了一个基于libevent的简单服务器和客户端,它们能够互相发送...
**iOS_libevent** libevent是一个开源的事件通知库,它为C语言编程提供了一种机制,可以在多个事件源上等待事件的发生。这个库特别适用于网络编程,如HTTP服务器、TCP和UDP服务器,以及处理定时任务。在iOS开发中,...
libEvent是一个跨平台的事件通知库,它允许程序员编写高性能的异步网络服务。本篇将深入探讨如何利用libEvent库在C++中实现HTTP的POST和GET请求。 首先,理解HTTP的基本概念至关重要。HTTP(超文本传输协议)是...