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. ...
随机推荐
- HTTPS为什么更安全,先看这些 , 网络加密 , 加密解密
投递人 itwriter 发布于 2017-02-27 21:35 评论(10) 有1957人阅读 原文链接 [收藏] « » HTTPS 是建立在密码学基础之上的一种安全通信协议,严格来说是基于 H ...
- OpenCV教程(48) 特征值匹配
OpenCV中通过下面的代码,可以匹配两幅的图像的特征值. // Read input images cv::Mat image1= cv::imread("../church0 ...
- Linux Shell脚本入门--wget 命令用法详解
Linux Shell脚本入门--wget 命令用法详解 wget是在Linux下开发的开放源代码的软件,作者是Hrvoje Niksic,后来被移植到包括Windows在内的各个平台上.它有以下功能 ...
- C/C++log日志库比较
事实上,在C的世界里面没有特别好的日志函数库(就像Java里面的的log4j,或者C++的log4cxx).C程序员都喜欢用自己的轮子.printf就是个挺好的轮子,但没办法通过配置改变日志的格式或者 ...
- jquery validate的漂亮css样式验证
自己结合了在网上找的验证功能和漂亮的提示同能后做出来的验证 希望大家喜欢 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...
- 使用SVD方法实现电影推荐系统
http://blog.csdn.net/zhaoxinfan/article/details/8821419 这学期选了一门名叫<web智能与社会计算>的课,老师最后偷懒,最后的课程pr ...
- 原:wireshare使用技巧收集
/data/local/tcpdump -p -vv -s 0 -w /sdcard/ThinkDrive.pcap 先抓一个pcap的包. 1. 查看所有的链接与流量 统计->对话 这 ...
- colspan width issue
[问] I'm having trouble setting fixed widths on columns which use colspan. It seems that neither IE8, ...
- Docker Inspect
1.Inspect结果详细信息 docker inspect 7988f914a122 其中7988f914a122是某一容器进程的id { "Id": "7988f91 ...
- 深度学习-Caffe中启用MatlabSupport编译出错的解决方案
一.如果编译前打算生成支持Matlab的库,则设置MatlabSupport为true之后. 二.记得添加Matlab的安装路径.我的是:D:\Application\DevTools\Matlab ...