Libevent官方代码样例学习(二)
连接监听器: 接收TCP连接请求
evconnlistener机制用于监听并接受TCP连接请求. 这些方法在event2/listener.h中声明, 在Libevent 2.0.2-alpha之后的版本中可用.
创建和释放evconnlistener
struct evconnlistener *evconnlistener_new( struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, evutil_socket_t fd);
struct evconnlistener *evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen);
void evconnlistener_free(struct evconnlistener *lev);
这两个 evconnlistener_new*() 方法都会allocate并返回一个新的connection listener对象. connection listener使用event_base 来通知来自于制定的socket上的新的TCP连接请求. 并调用预设的回调方法.
这两个方法相同的参数:
base 是listener用来监听的event_base.
cb 是回调方法, 如果cb is NULL, listener会被视为禁用, 直到回调被设置.
ptr 指针会作为参数被传递给回调方法.
flags 参数控制listener的行为.
backlog 参数控制允许的等待的连接数的上限. 如果backlog是负数, Libevent会自动设置一个合适的值, 如果为0, 则Libevent会认为你已经在socket上调用了listen()方法.
这两个方法中不同的参数, 在于如何初始化listener socket. evconnlistener_new() 方法假定你已经在要监听的端口上绑定了socket, 你只需要传递socket的fd就够. 如果你希望Libevent自己allocate并绑定socket, 就调用evconnlistener_new_bind(), 并传入你想监听的的sockaddr和它的length.
|
Tip
|
[使用 evconnlistener_new时要确保监听的socket工作于non-blocking 状态, (用evutil_make_socket_nonblocking 或手工指定正确的socket选项). When the listening socket is left in blocking mode, undefined behavior might occur.] |
要释放一个 listener, 使用evconnlistener_free().
创建一个signal events
Libevent can also watch for POSIX-style signals. 要创建一个signal的handler, 使用接口:
#define evsignal_new(base, signum, cb, arg) event_new(base, signum, EV_SIGNAL|EV_PERSIST, cb, arg)
可以看到其实是调用了event_new, 只不过flag是EV_SIGNAL|EV_PERSIST, 并且不是传fd而是传signum
struct event *hup_event;
struct event_base *base = event_base_new(); /* call sighup_function on a HUP signal */
hup_event = evsignal_new(base, SIGHUP, sighup_function, NULL);
注意: signal回调在signal发生后, 在event loop中执行, 所以一些在常规POSIX信号handler中不能调用的方法是可以在这种情况下调用的.
|
注意
|
不要在signal event中设置timeout |
另外一些相关的宏设定:
#define evsignal_add(ev, tv) \
event_add((ev),(tv))
#define evsignal_del(ev) \
event_del(ev)
#define evsignal_pending(ev, what, tv_out) \
event_pending((ev), (what), (tv_out))
evsignal_* 宏定义也是在Libevent 2.0.1-alpha之后的版本中可用.
例子
/*
This example program provides a trivial server program that listens for TCP
connections on port 9995. When they arrive, it writes a short message to
each client connection, and closes each connection once it is flushed.
Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
*/
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h> static const char MESSAGE[] = "Hello, World!\n";
static const int PORT = ;
static void listener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);
static void conn_writecb(struct bufferevent *, void *);
static void conn_eventcb(struct bufferevent *, short, void *);
static void signal_cb(evutil_socket_t, short, void *); int
main(int argc, char **argv) {
struct event_base *base;
struct evconnlistener *listener;
struct event *signal_event;
struct sockaddr_in sin; base = event_base_new();
if (!base) {
fprintf(stderr, "Could not initialize libevent!\n");
return ;
} memset(&sin, , sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
listener = evconnlistener_new_bind(
base, listener_cb, (void *) base, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -,
(struct sockaddr *) &sin, sizeof(sin)); if (!listener) {
fprintf(stderr, "Could not create a listener!\n");
return ;
} signal_event = evsignal_new(base, SIGINT, signal_cb, (void *) base); if (!signal_event || event_add(signal_event, NULL) < ) {
fprintf(stderr, "Could not create/add a signal event!\n");
return ;
} event_base_dispatch(base);
evconnlistener_free(listener);
event_free(signal_event);
event_base_free(base);
printf("done\n");
return ;
} static void
listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data) {
struct event_base *base = user_data;
struct bufferevent *bev; bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if (!bev) {
fprintf(stderr, "Error constructing bufferevent!");
event_base_loopbreak(base);
return;
}
bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL);
bufferevent_enable(bev, EV_WRITE);
bufferevent_disable(bev, EV_READ);
bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
} static void
conn_writecb(struct bufferevent *bev, void *user_data) {
struct evbuffer *output = bufferevent_get_output(bev);
if (evbuffer_get_length(output) == ) {
printf("flushed answer\n");
bufferevent_free(bev);
}
} static void
conn_eventcb(struct bufferevent *bev, short events, void *user_data) {
if (events & BEV_EVENT_EOF) {
printf("Connection closed.\n");
} else if (events & BEV_EVENT_ERROR) {
printf("Got an error on the connection: %s\n", strerror(errno));/*XXX win32*/
}
/* None of the other events can happen here, since we haven't enabled
* timeouts */
bufferevent_free(bev);
} static void
signal_cb(evutil_socket_t sig, short events, void *user_data) {
struct event_base *base = user_data;
struct timeval delay = {, };
printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
event_base_loopexit(base, &delay);
}
Libevent官方代码样例学习(二)的更多相关文章
- Libevent官方代码样例学习(一)
在Ubuntu16.04中, libevent的默认安装位置为 #在 trusty 发行版中 amd64 硬件架构下的 libevent- 软件包文件清单 /usr/lib/x86_64-linux- ...
- scrapy爬虫学习系列二:scrapy简单爬虫样例学习
系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备: http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...
- 33个超级有用必须要收藏的PHP代码样例
作为一个正常的程序员,会好几种语言是十分正常的,相信大部分程序员也都会编写几句PHP程序,如果是WEB程序员,PHP一定是必备的,即使你没用开发过大型软件项目,也一定多少了解它的语法. 在PHP的流行 ...
- java servlet 代码样例 (demo)
今天又搞了下jsp +servlet 的代码样例,感觉虽然搭了好多次,可是每次还是不记得那些参数,都要去网上搜索,索性自己把这次的简单demo给记录下来,供下次使用的时候直接复制吧. 这个web逻辑 ...
- 模式识别 - 处理多演示样例学习(MIL)特征(matlab)
处理多演示样例学习(MIL)特征(matlab) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/27206325 多演示样例学习( ...
- 2020JAVA最新应对各种OOM代码样例及解决办法
引言 作者:黄青石 链接:https://www.cnblogs.com/huangqingshi/p/13336648.html?utm_source=tuicool&utm_medium= ...
- zookeeper实战:SingleWorker代码样例
我们需要一个“单点worker”系统,此系统来确保系统中定时任务在分布式环境中,任意时刻只有一个实例处于活跃:比如,生产环境中,有6台机器支撑一个应用,但是一个应用中有30个定时任务,这些任务有些必须 ...
- 30个php操作redis经常用法代码样例
这篇文章主要介绍了30个php操作redis经常用法代码样例,本文事实上不止30个方法,能够操作string类型.list类型和set类型的数据,须要的朋友能够參考下 redis的操作非常多的,曾经看 ...
- JAVA各种OOM代码样例及解决方法
周末了,觉得我还有很多作业没有写,针对目前大家对OOM的类型不太熟悉,那么我们来总结一下各种OOM出现的情况以及解决方法. 我们把各种OOM的情况列出来,然后逐一进行代码编写复现和提供解决方法. 1. ...
随机推荐
- C++/Php/Python 语言执行shell命令
编程中经常需要在程序中使用shell命令来简化程序,这里记录一下. 1. C++ 执行shell命令 #include <iostream> #include <string> ...
- jQuery-append添加元素click无效
很久没有使用jQuery,做项目的时候遇到一个小问题就是网页加载之后的append的元素是可以执行click事件,网页加载完成之后的,再次append的元素不执行click事件,简单的通过ul模拟一下 ...
- Limu:有关JavaScript的那些值得一看的书
来源&作者:Limu 又好久没写东西了 ,写上一篇的时候还以为接下来的工作会轻松一些 ,结果未从我所愿呐 ,又是一阵忙碌.而这段时间穿插着做了很多12年淘宝校园招聘的前端面试 ,很多同学都有问 ...
- 原生JS实现new方法、new一个对象发生的四部、new里面常用的优先级
一.js中new一个对象的过程 首先了解new做了什么,使用new关键字调用函数(new ClassA(…))的具体步骤: 1.创建一个新对象: var obj = {}; 2.设置新对象的const ...
- iOS runtime探究(三): 从runtime開始理解OC的属性property
你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639303 本文主要解说runtime相关知识, ...
- [BUG] Dashboard报错:if usages['subnets']['available'] <= 0: KeyError: 'available'
Openstack版本号:Liberty 系统平台:CentOS 7.2 64bit ######################################################### ...
- git pull fails “unable to resolve reference” “unable to update local ref”
问题 由于有人rebase了分支,或者不知道怎么搞的.其他人拉取代码的时候,发现拉不下来. >git fetch error: cannot lock ref 'refs/remotes/ori ...
- http://blog.csdn.net/u014595019/article/details/52805444
http://blog.csdn.net/u014595019/article/details/52805444 tensorflow笔记系列: (一) tensorflow笔记:流程,概念和简单代码 ...
- How to duplicate the records in a MongoDB collection
// Fill out a literal array of collections you want to duplicate the records in. // Iterate over e ...
- oracle 嵌套查询
select dat.id, dat.voucher_id, dat.type, dat.state, dat.start_point, dat.start_floor, dat.end_point, ...