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 = 5; tv1.tv_usec = 500*1000;

/* 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[2]);

随机数生成

该函数生成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


本文 由 cococo点点 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:
转载自:cococo点点 http://www.cnblogs.com/coder2012

时间: 2024-11-07 04:23:17

socket属性设置与初始化操作的相关文章

js-JavaScript 操作querytables 属性设置不了,求各位大侠帮忙

问题描述 JavaScript 操作querytables 属性设置不了,求各位大侠帮忙 js把TXT数据导入到EXCEL中,使用的是QueryTables.Add方法,JS如何设置QueryTable的TextFileColumnDataTypes?用数组赋值总显示是参数不正,着急使用,跪求各位大侠帮忙!!! txt文件的格式是 "01","12","www","002", 想要的EXCEL中数据结果是:01 12 www

pthread_create()之前的属性设置

一.pthread_create()之前的属性设置1.线程属性设置我们用pthread_create函数创建一个线程,在这个线程中,我们使用默认参数,即将该函数的第二个参数设为NULL.的确,对大多数程序来说,使用默认属性就够了,但我们还是有必要来了解一下线程的有关属性.属性结构为pthread_attr_t,它同样在头文件pthread.h中定义,属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用

数据库属性设置

    在创建数据库以后还可以设置其属性,以更改创建时的某些设置和创建时无法设置的属性.用右键单击所要设置属性的数据库,从快捷菜单中选择选项"属性(Properties)",就会出现如图6-4 所示的数据库属性设置对话框.     在"General"页框中,可以看到数据库的状态.所有者.创建时间.容量.备份.维护等属性信息.     在"Data Files" 和"Transaction Log" 页框中,可以看到类似于图6

Visual C++ 2005图像编程之属性设置栏

工具箱含有选择.填充.画线等功能.使用这些工具时有的需要设置填充风格和线条的大小.为了方便用户操作,实现更简易的UI,实现了属性工具栏.属性栏需要添加的主要功能有2个显示文字的静态文本框和2个组合框. 添加属性栏控件,需要先通过资源编辑器在相应的位置上建立四个对应的工具栏按钮,对于没有接触过Visual C++ 2005的朋友可能会找不到按钮的属性编辑器.在Visual C++ 6.0中是回车(右键)弹出对话框设置的.默认情况下,在工具栏右边可以打开属性设置对话框.注意下图中红色数字的位置就是我

如何在win8电脑中打开vpn属性设置面板

  设置VPN连接,想必很多朋友在日常的电脑操作中都曾经涉及到过吧?在之前的win7 64位旗舰版下载中,咱们启动VPN设置是十分简单的,直接在连接的右键菜单中就可以找到,但是升级到win8系统之后,这样的设置方法就不行了,想必很多用户都已经发现了吧!这样的快捷设置功能已经没有了,那么对于刚升级到win8系统的用户来说,大家知道在win8电脑中要如何打开VPN属性设置窗口呢?下面,小编就来详细的介绍一下吧! 1.首先,咱们需要打开win8电脑的传统桌面,之后,咱们在打开的界面中找到右下角的网络连

win7 64位旗舰版鼠标如何才能设置成左手操作

  由于个人使用习惯摆脱那个,有的人习惯用左手吃饭,左手写字,甚至也用左手用鼠标,这虽然看上去是一个比较小众的应用,但是,如果你或者你的好友正好遇到有这个需求,又该怎么解决呢?下面就来看看win7 64位旗舰版鼠标设置成左手操作的具体方法. 1.首先我们需要做的就是上网找到反向鼠标指针,然后找打安全的下载方式直接下载下来. 2.接着就点击键盘上面的Windows键,也可以直接单击开始菜单,这时候就会来到控制面板界面.在这个界面里面找到右上角查看方式后面设置,直接更改成大图标,接着就在窗口里面找到

visual studio 2010-64位系统编写MFC程序通过ado连接Oracle在项目属性设置为win32平台时调试出错

问题描述 64位系统编写MFC程序通过ado连接Oracle在项目属性设置为win32平台时调试出错 我64位的系统用VS2010编写MFC程序,通过ADO方式连接Oracle数据库,在项目属性中设置为x64平台时,程序调试可以正常的连接数据库并对数据库进行增删改查等操作:但是将项目属性设置为win32平台时,程序调试就停在连接数据库那一语句并报有未经处理的异常,请问到底是什么原因啊?应该如何解决? 解决方案 数据库引擎是否支持32bit程序访问.你的ADO等方式配置是否有平台依赖性的地方

linux多线程学习(三)——线程属性设置。

在上一篇文章中,介绍了线程的创建和退出,以及相关函数的使用.其中pthread_create函数的第二个参数,是关于线程属性的设置,这也是今天所有讲述的.这些属性主要包括邦定属性.分离属性.堆栈地址.堆栈大小.优先级.其中系统默认的是非邦定.非分离.缺省1M的堆栈.与父进程同样级别的优先级.在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置. (1)绑定属性. 在LINUX中,采用的是"一对一"的线程机制.也就是一个用户线程对应一个内核线程.邦定属性

C#3.0之自动属性和对象初始化器

C#3.0中定义属性更加方便,不用再在像之前的版本那样的繁琐,需要先定义存储数据的字段,然后再定义属性器,现在只需要定义属性器就可以了,其它的有编译器自动为我们完成,就可以省去定义字段时需要的那些时间:在对象初始化的时候我们可在对象构造的时候实现对象属性的初始化工作,和集合初始化类似. 1.匿名属性 定义属性如下: public class Employee { public int Id { get; set; } public string Name { get; set; } public