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. UART IP和UVM的验证平台

    UART是工程师在开发调试时最常用的工具的,其通信协议简单.opencores 网站提供了兼容16550a的UART IP其基本特性如下: uart16550 is a 16550 compatibl ...

  2. sqlserver无法连接

    以下是我的检查信息及结果:1.telnet 192.168.1.100 1433 通过  telnet 116.3.15.198 1433 不通,提示“……无法打开连接,连接失败”的错误.2.通过端口 ...

  3. 【软件工程】电梯调度程序需求分析 李亚文&&郭莉莉

    2014年3月4日(14:00-16:00) 为了进一步理解电梯工作的原理,我们特地到石家庄铁道大学春晖楼坐了电梯:春晖楼东办共有电梯两部,最高楼层为11层,最低楼层为-1,两电梯可共同使用.结合调查 ...

  4. for 循环

    #include <iostream> int main(){ ; ; val <= ; ++val) { sum += val; } std::cout << &quo ...

  5. 【C#】 一些不常用,很容易混淆的知识点

    [C#] 一些不常用但很容易混淆的知识点 1. 访问修饰符 internal ,译为内部的, 在同一个程序集中可访问,它的内部是相对与程序集的,可不能想当然了 2. String.Compare 这个 ...

  6. The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决

    问题 The certificate used to sign "AppName" has either expired or has been revoked. An updat ...

  7. 钩子机制(hook)

    钩子是编程惯用的一种手法,用来解决一种或多种特殊情况的处理. 简单来说,钩子就是适配器原理,或者说是表驱动原理,我们预先定义了一些钩子,在正常的代码逻辑中使用钩子去适配一些特殊的属性,样式或事件,这样 ...

  8. Centos7 安装MPlayer过程详解

    使用自带的totem基本上都无法播放视频,各种格式都不支持,令人无语.想到了MPlayer,为了看片,决定编译安装,过程真的是折腾.如图是自带的Totem播放提示,安装了解码还是无法播放,反正要找其他 ...

  9. SparkContext的初始化(叔篇)——TaskScheduler的启动

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

  10. c# (nop中)下拉列表(有外键)

    第一种情况.view视图加载出来时就有值,实现步骤如下 1.在操作的界面Model中建立public List<SelectListItem> xxx(取名){ get; set; } 2 ...