学习笔记:高性能IO框架库Libevent(三):辅助类型和函数

661 阅读3分钟

1.基本类型

evutil_socket_t:

除了windows之外的系统socket句柄都是一个int,而windows下是一个特定的socket api定义的类型

#ifdef WIN32
#define evutil_socket_t intptr_t
#else
#define evutil_socket_t int
#endif

标准的整数类型: 用来兼容c99之前的系统

标题WidthSignedMaximumMinimum
ev_uint64_t64NoEV_UINT64_MAX0
ev_int64_t64YesEV_INT64_MAXEV_INT64_MIN
ev_uint32_t32NoEV_UINT32_MAX0
ev_int32_t32YesEV_INT32_MAXEV_INT32_MIN
ev_uint16_t16NoEV_UINT16_MAX0
ev_int16_t16YesEV_INT16_MAXEV_INT16_MIN
ev_uint8_t8NoEV_UINT8_MAX0
ev_int8_t8YesEV_INT8_MAXEV_INT8_MIN

2.定时器可移植函数

不是所有系统中中会定义timeval功能 附:linux中timeval包含在<time.h>中

\\linux
struct timeval
{
     __time_t tv_sec;                /* Seconds. */
     __suseconds_t tv_usec;      /* Microseconds. */
};

其中,tv_sec为Epoch(1970-1-1零点零分)到创建struct timeval时的秒数,tv_usec为微秒数,即秒后面的零头。 为了满足跨平台的需求,libevent实现了以下timeval功能

#define evutil_timeradd(tvp, uvp, vvp) /* ... */ \\事件相加
#define evutil_timersub(tvp, uvp, vvp) /* ... */  \\时间相减
#define evutil_timerclear(tvp) /* ... */ \\ 清0
#define evutil_timerisset(tvp) /* ... */ \\检查时间是否为0,非0返回true
#define	evutil_timercmp(tvp, uvp, cmp) \\时间比较 
int evutil_gettimeofday(struct timeval *tv, struct timezone *tz);\\通过tv获取当前时间,不使用tz

示例代码:

//BUILD: FUNCTIONBODY INC:event2/util.h INC:stdio.h
.Example
[code,C]
--------
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.");

3.套接字API兼容性

int evutil_closesocket(evutil_socket_t s); 

#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s) \\兼容windows和其他平台的套接字关闭函数 
#define EVUTIL_SOCKET_ERROR() \\返回本线程最后一次套接字操作的全局错误号
#define EVUTIL_SET_SOCKET_ERROR(errcode) \\返回某指定socket的错误号
#define evutil_socket_geterror(sock) \\修改当前套接字错误号
#define evutil_socket_error_to_string(errcode) \\字符串形式返回某指定套接字的错误号
int evutil_make_socket_nonblocking(evutil_socket_t sock); \\套接字非阻塞IO调用
int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
\\关闭监听套接字后,它使用的地址可以立即被另一个套接字使用
int evutil_make_socket_closeonexec(evutil_socket_t sock);\\如果调用了 exec(),应该关闭指定的套接字。
int evutil_socketpair(int family, int type, int protocol,evutil_socket_t sv[2]);
\\创建两个相互连接起来的套接字,可对其使用普通套接字 IO 调用。

4.可移植的字符串操作函数

ev_int64_t evutil_strtoll(const char *s, char **endptr, int base);\\类似strtol,base为进制
int evutil_snprintf(char *buf, size_t buflen, const char *format, ...);\\代替snprintf
int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap);\\代替vsnsprintf
\\总是使用ASCII字符集进行比较
int evutil_ascii_strcasecmp(const char *str1, const char *str2);
int evutil_ascii_strncasecmp(const char *str1, const char *str2, size_t n);

5.IPV6辅助和兼容性函数

这些函数根据 RFC 3493的规定解析和格式化 IPv4与 IPv6地址,与标准 inet_ntop()和 inet_pton()函数行为相同。

const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len);
int evutil_inet_pton(int af, const char *src, void *dst);

int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out,
    int *outlen);

int evutil_sockaddr_cmp(const struct sockaddr *sa1,
    const struct sockaddr *sa2, int include_port);

6.结构体可移植性函数

代替标准offsetof宏

#define evutil_offsetof(type, field) /* ... */

7.随机数产生器

这个函数用随机数据填充 buf 处的 n 个字节。如果所在平台提供了 arc4random(),libevent 会使用这个函数。否则,libevent 会使用自己 的 arc4random()实现,种子则来自操作系统的熵池(entropy pool)(Windows 中的 CryptGenRandom,其他平台中的/dev/urandom)

不需要手动初始化安全随机数发生器,但是如果要确认已经成功初始化,可以调 用 evutil_secure_rng_init()。函数会播种 RNG(如果没有播种过),并在成功时返回0。函数返 回-1则表示 libevent 无法在操作系统中找到合适的熵源(source of entropy),如果不自己 初始化 RNG,就无法安全使用 RNG 了。

如果程序运行在可能会放弃权限的环境中(比如说,通过执行 chroot()),在放弃权限前应 该调用 evutil_secure_rng_init()。 可以调用 evutil_secure_rng_add_bytes()向熵池加入更多随机字节,但通常不需要这么做。

void evutil_secure_rng_get_bytes(void *buf, size_t n); \\用随机数据填充 buf 处的 n 个字节
int evutil_secure_rng_init(void);
void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);