(转)Libevent(5)— 连接监听器
转自:http://name5566.com/4220.html
参考文献列表:
http://www.wangafu.net/~nickm/libevent-book/
此文编写的时候,使用到的 Libevent 为 2.0.21
Libevent 提供了连接监听器 evconnlistener
创建 evconnlistener 实例
- // 连接监听器回调函数原型
- typedef void (*evconnlistener_cb)(
- struct evconnlistener *listener,
- // 新的 socket
- evutil_socket_t sock,
- // 新的 socket 对应的地址
- struct sockaddr *addr,
- int len,
- // 用户自定义数据
- void *ptr
- );
- // 创建一个新的连接监听器
- struct evconnlistener *evconnlistener_new(
- struct event_base *base,
- // 一个新的连接到来时此回调被调用
- evconnlistener_cb cb,
- // 用户自定义数据,会被传递给 cb 回调函数
- void *ptr,
- // 连接监听器的选项(下面会详细谈到)
- unsigned flags,
- // 为标准的 listen 函数的 backlog 参数
- // 如果为负数,Libevent 将尝试选择一个合适的值
- int backlog,
- // socket
- // Libevent 假定此 socket 已经绑定
- evutil_socket_t fd
- );
- // 创建一个新的连接监听器
- // 大多数参数含义同于 evconnlistener_new
- struct evconnlistener *evconnlistener_new_bind(
- struct event_base *base,
- evconnlistener_cb cb,
- void *ptr,
- unsigned flags,
- int backlog,
- // 指定需要绑定的 socket 地址
- const struct sockaddr *sa,
- int socklen
- );
连接监听器的常用选项如下:
- LEV_OPT_CLOSE_ON_FREE
当关闭连接监听器其底层 socket 也被自动释放 - LEV_OPT_REUSEABLE
设置 socket 绑定的地址可以重用 - LEV_OPT_THREADSAFE
设置连接监听器为线程安全的
释放连接监听器
- void evconnlistener_free(struct evconnlistener *lev);
错误检测
如果连接监听器出错,我们可以得到通知:
- // 连接监听器错误回调函数原型
- typedef void (*evconnlistener_errorcb)(struct evconnlistener *lis, void *ptr);
- // 为连接监听器设置错误回调函数
- void evconnlistener_set_error_cb(struct evconnlistener *lev,
- evconnlistener_errorcb errorcb);
一个详细的范例(echo 服务器)
- #include <event2/listener.h>
- #include <event2/bufferevent.h>
- #include <event2/buffer.h>
- #include <arpa/inet.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- // 读取回调函数
- static void
- echo_read_cb(struct bufferevent *bev, void *ctx)
- {
- struct evbuffer *input = bufferevent_get_input(bev);
- struct evbuffer *output = bufferevent_get_output(bev);
- // 将输入缓冲区的数据直接拷贝到输出缓冲区
- evbuffer_add_buffer(output, input);
- }
- // 事件回调函数
- static void
- echo_event_cb(struct bufferevent *bev, short events, void *ctx)
- {
- if (events & BEV_EVENT_ERROR)
- perror("Error from bufferevent");
- if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
- bufferevent_free(bev);
- }
- }
- // 连接监听器回调函数
- static void
- accept_conn_cb(struct evconnlistener *listener,
- evutil_socket_t fd, struct sockaddr *address, int socklen,
- void *ctx)
- {
- // 为新的连接分配并设置 bufferevent
- struct event_base *base = evconnlistener_get_base(listener);
- struct bufferevent *bev = bufferevent_socket_new(
- base, fd, BEV_OPT_CLOSE_ON_FREE);
- bufferevent_setcb(bev, echo_read_cb, NULL, echo_event_cb, NULL);
- bufferevent_enable(bev, EV_READ|EV_WRITE);
- }
- // 连接监听器错误回调函数
- static void
- accept_error_cb(struct evconnlistener *listener, void *ctx)
- {
- struct event_base *base = evconnlistener_get_base(listener);
- // 获取到错误信息
- int err = EVUTIL_SOCKET_ERROR();
- fprintf(stderr, "Got an error %d (%s) on the listener. "
- "Shutting down.\n", err, evutil_socket_error_to_string(err));
- // 退出事件循环
- event_base_loopexit(base, NULL);
- }
- int
- main(int argc, char **argv)
- {
- struct event_base *base;
- struct evconnlistener *listener;
- struct sockaddr_in sin;
- int port = 9876;
- if (argc > 1) {
- port = atoi(argv[1]);
- }
- if (port<=0 || port>65535) {
- puts("Invalid port");
- return 1;
- }
- base = event_base_new();
- if (!base) {
- puts("Couldn't open event base");
- return 1;
- }
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(0);
- sin.sin_port = htons(port);
- listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
- LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
- (struct sockaddr*) & sin, sizeof(sin));
- if (!listener) {
- perror("Couldn't create listener");
- return 1;
- }
- evconnlistener_set_error_cb(listener, accept_error_cb);
- event_base_dispatch(base);
- return 0;
- }
(转)Libevent(5)— 连接监听器的更多相关文章
- libevent系列文章
Libevent 2 提供了 bufferevent 接口,简化了编程的难度,bufferevent 实际上是对底层事件核心的封装,因此学习 bufferevent 的实现是研究 Libevent 底 ...
- 项目中的libevent
单线程libevent模式 项目里面是多线程版的,我先理解下单线程的. //client .调用NGP::init() bool NGP::init(NGPcontext context) { _co ...
- libevent入门
Libevent API =============================== evtimer_new evtimer_new(base, callback, NULL) 用来做定时器,即当 ...
- Libevent API
evtimer_new evtimer_new(base, callback, NULL) 用来做定时器,即当达到一定时间后调用回调函数callback.用evtimer_add激活定时器.比如: m ...
- Libevent官方代码样例学习(二)
连接监听器: 接收TCP连接请求 evconnlistener机制用于监听并接受TCP连接请求. 这些方法在event2/listener.h中声明, 在Libevent 2.0.2-alpha之后的 ...
- libevent编程疑难解答
http://blog.csdn.net/luotuo44/article/details/39547391 转载请注明出处:http://blog.csdn.net/luotuo44/article ...
- Oracle 监听器
Oracle监听器listener是一个重要的数据库服务器组件,在整个Oracle体系结构中,扮演着重要的作用. 监听器Lisener功能 从当前的Oracle版本看,Listener主要负责下面的几 ...
- Android基于XMPP Smack Openfire下学习开发IM(五)连接断开重连
学习过程中大家都碰到过连接被断开的问题给困扰吧,下面教大家如何做到连接断开后,重新连接 首先要创建连接监听器,用来监听连接状态,这里我写了一个类 继承了ConnectionListener,重写了里面 ...
- Openfire分析之三:ConnectionManager 连接管理(1)
Openfire是怎么实现连接请求的? XMPPServer.start()方法,完成Openfire的启动.但是,XMPPServer.start()方法中,并没有提及如何监听端口,那么Openfi ...
随机推荐
- HW4.46
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
- HDOJ-ACM1022(JAVA)
这道题:是模拟出栈,判断出栈顺序的可能性. 基本上大家的做法都是直接模拟栈的出栈入栈并将顺序用0,1序列来表示,我暂时没想到什么好的思路. import java.util.*; import jav ...
- HDU1247 - Hat’s Words(Trie树)
题目大意 给定一些单词,要求你把所有的帽子单词找出来,如果某个单词恰好由另外两个单词连接而成,那么它就是帽子单词 题解 先把所有单词插入到Trie树,然后判断每个单词是不是帽子单词,做法就是:对于第i ...
- 【ACM/ICPC2013】POJ基础图论题简析(一)
前言:昨天contest4的惨败经历让我懂得要想在ACM领域拿到好成绩,必须要真正的下苦功夫,不能再浪了!暑假还有一半,还有时间!今天找了POJ的分类题库,做了简单题目类型中的图论专题,还剩下二分图和 ...
- json.net json转换神器
json.nethttps://json.codeplex.com/ api documenthttp://james.newtonking.com/json/help/index.html#
- 整理收藏一份PHP高级工程师的笔试题
整理了一份PHP高级工程师的笔试题,问题很全面.嗯,基本上这些题都答得不错,那么你应该可以胜任大部分互联网企业的PHP职位了.下面直接上题. 1. 基本知识点 HTTP协议中几个状态码的含义:503, ...
- 1514:数值的整数次方 @jobdu
题目1514:数值的整数次方 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:377 解决:103 题目描述: 给定一个double类型的浮点数base和int类型的整数exponent. ...
- java中用线程解决进出水问题
//进水 class Inflow implements Runnable{ //水对象 Water wat; public Inflow(Water w){ this.wat = w; } @Ove ...
- CopyU!v2.2 增加对设备信息的识别
更新版本的CopyU!v2.2已经完成大部分功能的设计,主打升级功能“设备信息识别”已经基本完成,现在放上测试截图:
- oncopy和onpaste
在Javascript中,有对应的事件能够监听复制和粘贴,那就是oncopy和onpaste. oncopy: demo: <body oncopy="alert('不能复制');re ...