socket属性设置与初始化操作

libevent是一个事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue等系统调用管理事件机制。著名分布式缓存软件memcached也是libevent based,而且libevent在使用上可以做到跨平台,而且根据libevent官方网站上公布的数据统计,似乎也有着非凡的性能。

event_base

在使用Libevent之前,需要初始化一个event_base结构。每一个event_base结构提包含了events集合并选择事件类型。如果选择locking方式,会保证交互是线程安全的。如果需要使用多线程模型的话,需要为每一个线程建立一个event_base。

method种类

select、poll、epoll、kqueue、devpoll、evport、win32

接口

#include <event2/event.h>
struct event_base *event_base_new(void);

`event_base_new`会根据默认的配置参数返回一个`event_base`结构体,失败返回`NULL`。

配置方法

struct event_config *event_config_new(void);
struct event_base *event_base_new_with_config(const struct event_config *cfg);
void event_config_free(struct event_config *cfg);

`event_config_new`可以返回一个配置信息的结构体,通过修改结构提内容,并作为参数传递给`event_base_new_with_config`可以生成目标`event_base`,而`event_config_free`使用来是放掉config配置信息的。

那么event_config到底是什么样的?

struct event_config {
TAILQ_HEAD(event_configq, event_config_entry) entries;
int n_cpus_hint; //cpu数量
enum event_method_feature require_features;//指定IO复用的条件
enum event_base_config_flag flags;
};

可以使用`event_config_set_num_cpus_hint(struct event_config *cfg, int cpus)`设置`n_cpu_hint`,但是目前只支持使用IOCP的情况下。

`require_features`的具体结构如下:

//event.h文件
enum event_method_feature {
//支持边沿触发
EV_FEATURE_ET = 0x01,
//添加、删除、或者确定哪个事件激活这些动作的时间复杂度都为O(1)
//select、poll是不能满足这个特征的.epoll则满足
EV_FEATURE_O1 = 0x02,
//支持任意的文件描述符,而不能仅仅支持套接字
EV_FEATURE_FDS = 0x04
};

通过`event_config_require_features(struct event_config *cfg, int features)`函数来设置`require_features`。

需要注意的是,当需要设置多个参数的时候需要使用 `EV_FEATURE_O1 | EV_FEATURE_FDS`操作,而不是多次调用该函数。如果设置不当,找不当对应的事件方法method,`event_base_new_with_config(cfg)会返回NULL`。

最后一个参数`flag`指定其他的配置:

enum event_base_config_flag {
//不分配锁(如果设置,保证线程安全)
EVENT_BASE_FLAG_NOLOCK = 0x01,
//不检测EVENT_*环境变量?
EVENT_BASE_FLAG_IGNORE_ENV = 0x02,
//win下的iocp
EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,
//?
EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,
//如果决定使用epoll这个多路IO复用函数,可以安全地使用更快的基于 changelist 的多路IO复用函数
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10,
//?
EVENT_BASE_FLAG_PRECISE_TIMER = 0x20
};

通过`event_config_set_flag(struct event_config *cfg, enum event_base_config_flag flag)`进行设置。

获取支持的配置

//获取当前系统支持的IO复用方法
const char **event_get_supported_methods(void);
//获取配置的IO复用方法
const char *event_base_get_method(const struct event_base *);
int event_base_get_features(const struct event_base *base);
//指明某个参数是否被禁用
static int event_config_is_avoided_method(const struct event_config *cfg, const char *method)

设置IO优先级

默认情况下会设置相同的优先级。

int event_base_priority_init(struct event_base *base, int n_priorities);
int event_base_get_npriorities(struct event_base *base);

fork使用parent进程中的event_base

int event_reinit(struct event_base *base);

#include <event2/event.h>
/* example */
struct event_base *base = event_base_new();
/* ... add some events to the event_base ... */
if (fork()) {
/* In parent */
continue_running_parent(base); /*...*/
} else {
/* In child */
event_reinit(base);
continue_running_child(base); /*...*/
}

libevent 函数

考虑到多个平台的兼容性(并不是所有平台都支持某一函数功能),`libevent`自身提供了很多函数以及数据类型,下面的函数均是是跨平台的,在Unix以及windows都可以正常运行。

定时函数

#define evutil_timeradd(tvp, uvp, vvp) /* 增加 vvp=tvp+uvp */
#define evutil_timersub(tvp, uvp, vvp) /* 减少 vvp=tvp-uvp */
#define evutil_timercmp(tvp, uvp, cmp) /* 比较 if (cmp=='<'), then ("tvp < uvp") */
int evutil_gettimeofday(struct timeval *tv, struct timezone *tz);
/* Set tv = now */
evutil_gettimeofday(&tv, NULL);
struct timeval tv1, tv2, tv3;

/* Set tv1 = 5.5 seconds */
tv1.tv_sec = ; tv1.tv_usec = *; /* Set tv2 = now */
evutil_gettimeofday(&tv2, NULL); /* Set tv3 = 5.5 seconds in the future */
evutil_timeradd(&tv1, &tv2, &tv3); /* all 3 should print true */
if (evutil_timercmp(&tv1, &tv1, ==)) /* == "If tv1 == tv1" */
puts("5.5 sec == 5.5 sec");
if (evutil_timercmp(&tv3, &tv2, >=)) /* == "If tv3 >= tv2" */
puts("The future is after the present.");
if (evutil_timercmp(&tv1, &tv2, <)) /* == "If tv1 < tv2" */ puts("It is no longer the past.")

兼容的Socket接口

关闭socket:在`unix`中,只需要调用`close()`,而在`windows`中需要调用`closesocket()`。

int evutil_closesocket(evutil_socket_t s);
#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s)

获取socket错误信息

#define EVUTIL_SOCKET_ERROR() /* 获取最新的全局错误信息 */
#define EVUTIL_SET_SOCKET_ERROR(errcode) /* 改变错误信息,等于设置错误 */
#define evutil_socket_geterror(sock) /* 指定sockfd,同1 */
#define evutil_socket_error_to_string(errcode) /* 把errcode转换为字符串 */

设置非阻塞模式

int evutil_make_socket_nonblocking(evutil_socket_t sock);

地址重用

int evutil_make_listen_socket_reuseable(evutil_socket_t sock);

socketpair
该函数和unix中的socketpair一样,它会产生两个连接socket,一个用于输入,一个用于输出。注意,在windows中,只支持family=AF_INET,type=SOCK_STREAM,protocol=0。

int evutil_socketpair(int family, int type, int protocol,evutil_socket_t sv[]);

随机数生成

该函数生成n长度的buf数据

void evutil_secure_rng_get_bytes(void *buf, size_t n);

参考

http://www.wangafu.net/~nickm/libevent-book/Ref2_eventbase.html
http://www.tuicool.com/articles/jaQ7vmZ

libevent (一) socket属性设置与初始化操作的更多相关文章

  1. 服务端socket重用属性设置

    初始化socket socket是一种系统资源,并不是每次初始化都一定成功,因此为了避免初始化失败,一般使用多次初始化的方式,如下所示: unsigned int times = 0x0; while ...

  2. c# WinForm开发 DataGridView控件的各种操作总结(单元格操作,属性设置)

    一.单元格内容的操作 *****// 取得当前单元格内容 Console.WriteLine(DataGridView1.CurrentCell.Value); // 取得当前单元格的列 Index ...

  3. 转:c# WinForm开发 DataGridView控件的各种操作总结(单元格操作,属性设置)

    一.单元格内容的操作 *****// 取得当前单元格内容 Console.WriteLine(DataGridView1.CurrentCell.Value); // 取得当前单元格的列 Index  ...

  4. DEV控件:gridControl常用属性设置(转载)

    特别长,先撸下来再说 1.隐藏最上面的GroupPanel  gridView1.OptionsView.ShowGroupPanel=false; 2.得到当前选定记录某字段的值  sValue=T ...

  5. DEV控件:gridControl常用属性设置

    1.隐藏最上面的GroupPanel  gridView1.OptionsView.ShowGroupPanel=false; 2.得到当前选定记录某字段的值  sValue=Table.Rows[g ...

  6. DEV控件GridControl常用属性设置

    1. 如何解决单击记录整行选中的问题 View->OptionsBehavior->EditorShowMode 设置为:Click 2. 如何新增一条记录 (1).gridView.Ad ...

  7. pthread_create()之前的属性设置

    一.pthread_create()之前的属性设置1.线程属性设置我们用pthread_create函数创建一个线程,在这个线程中,我们使用默认参数,即将该函数的第二个参数设为NULL.的确,对大多数 ...

  8. DEV控件GridControl常用属性设置(转)

      1. 如何解决单击记录整行选中的问题 View->OptionsBehavior->EditorShowMode 设置为:Click 2. 如何新增一条记录 (1).gridView. ...

  9. python类内init外声明的属性与init内声明的对象属性的访问和操作区别

    python类内init外声明的属性与init内声明的对象属性的访问和操作区别(面试题) 1.在ipython中输入以下代码,其输出会是什么? In [1]: class ClassOut: ...: ...

随机推荐

  1. 最小生成树(HDOJ 1863)

    畅通工程 http://acm.hdu.edu.cn/showproblem.php?pid=1863 1.Prim算法: Prim算法是由一个点(最初的集合)向外延伸,找到与集合相连权值最小的边, ...

  2. CentOS 安装 chrome 浏览器

    安装 google-chrome 浏览器,由于众所周知的原因,一直安装不了,下面介绍一种新方法. cd 到 /etc/yum.repos.d 创建一个yum新源 vi chromium-el6.rep ...

  3. poj3241 曼哈顿最小距离生成树第k大的边

    思路: 已知: 要生成曼哈顿距离最小生成树,一个点最多和四周8个点连线,那8个点分别是将那个点四周360度平分成8个区间,每个区间里面和那个点曼哈顿距离最小的点,所以如果有n个点,那么最多有4n条边, ...

  4. python学习笔记2-functools.wraps 装饰器

    wraps其实没有实际的大用处, 就是用来解决装饰器导致的原函数名指向的函数 的属性发生变化的问题: 装饰器装饰过函数func, 此时func不是指向真正的func,而是指向装饰器中的装饰过的函数 i ...

  5. SQL Server数据库表重置自增主键号(通常是指ID)

    执行 DBCC CHECKIDENT ('table_name', NORESEED) 以确定列中的当前最大值 然后使用 DBCC CHECKIDENT ('table_name', RESEED,n ...

  6. [2015hdu多校联赛补题]hdu5324 Boring Class

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5324 题意:给你一个二维的序列,让你找出最长的第一维升第二维降的子序列(如果多个答案,输出字典序最小) ...

  7. jquery :checked(过滤选择器) 和 空格:checked(后代选择器)

    jquery 过滤选择器 和 后代选择器 <%@ page language="java" contentType="text/html; charset=UTF- ...

  8. Codeforces Round #383 _python作死系列

    A. Arpa's hard exam and Mehrdad's naive cheat 题意求1378的n次方的最后一位,懒的写循环节 瞎快速幂 py3 int和LL 合并为int了 def q_ ...

  9. 快速排序(java实现)

    快速排序 算法思想:基于分治的思想,是冒泡排序的改进型.首先在数组中选择一个基准点(该基准点的选取可能影响快速排序的效率,后面讲解选取的方法),然后分别从数组的两端扫描数组,设两个指示标志(lo指向起 ...

  10. [转]初探 PhoneGap 框架在 Android 上的表现

    原文地址:http://topmanopensource.iteye.com/blog/1486929 phonegap是由温哥华的一家小公司研发的多平台的移动开发框架,支持流行的大多数移动设备(iP ...