jsp 企业建站,四川达州网站建设,邓亚萍做的网站,做网站i3够用吗在头文件event2/util.h中定义了许多有用的函数和类型来帮助实现可移植的程序。Libevent在内部使用这些类型和函数。 一#xff1a;基本类型 evutil_socket_t 除了Windows之外的大多数系统#xff0c;socket就是一个整数#xff0c;而且操作系统按照数值顺序对它们进… 在头文件event2/util.h中定义了许多有用的函数和类型来帮助实现可移植的程序。Libevent在内部使用这些类型和函数。 一基本类型 evutil_socket_t 除了Windows之外的大多数系统socket就是一个整数而且操作系统按照数值顺序对它们进行处理。而在Windows socket API中socket是SOCKET类型该类型是一个类似于指针的OS句柄而且得到它们的顺序也是未定义的。Libevent定义evutil_socket_t类型为一个整数该整数可以表示socket或者accept函数的返回值并且可以在Windows上避免指针截断的风险。 #ifdef WIN32 #define evutil_socket_t intptr_t #else #define evutil_socket_t int #endif 标准整数类型 有时你的C系统可能落后于21世纪因此并没有实现C99标准的stdint.h头文件。这种情况下Libevent自己定义了stdint.h中的确定位宽度bit-width-specific的整数。 Type Width Signed Maximum Minimum ev_uint64_t 64 No EV_UINT64_MAX 0 ev_int64_t 64 Yes EV_INT64_MAX EV_INT64_MIN ev_uint32_t 32 No EV_UINT32_MAX 0 ev_int32_t 32 Yes EV_INT32_MAX EV_INT32_MIN ev_uint16_t 16 No EV_UINT16_MAX 0 ev_int16_t 16 Yes EV_INT16_MAX EV_INT16_MIN ev_uint8_t 8 No EV_UINT8_MAX 0 ev_int8_t 8 Yes EV_INT8_MAX EV_INT8_MIN 类似于C99标准这些类型都有确定的位宽度。 各种兼容性类型 在那些具有ssize_t的类型的平台上ev_ssize_t就被定义为ssize_tsignedsize_t对于没有这种类型的平台ev_ssize_t会被定义为合理的默认值。ev_ssize_t类型可能的最大值是EV_SSIZE_MAX最小值为EV_SSIZE_MIN。在平台没有定义SIZE_MAX的时候size_t类型的最大可能值是EV_SIZE_MAX ev_off_t类型用来表示一个文件或一段内存中的偏移值。在那些具有合理的off_t类型定义的系统上ev_off_t被定义为off_t在Windows上被定义为ev_int4_t。 某些socket API的实现提供了长度类型socklen_t而某些却没有提供。在那些提供该类型的平台上ev_uintptr_t就被定义为socklen_t而那些没有定义的平台ev_socklen_t被定义为一个合理的默认值。 ev_intptr_t类型是一个具有足够大的空间来保存一个指针而不会丢失位的有符号整数类型。ev_uintptr_t类型是一个具有足够大的空间来保存一个指针而不会丢失位的无符号整数类型。 二可移植的定时器函数 并不是所有的平台都定义了标准的timeval操作函数所以Libevent提供了自己的实现。 #define evutil_timeradd(tvp, uvp, vvp) /* ... */ #define evutil_timersub(tvp, uvp, vvp) /* ... */ 这些宏会将其前两个参数进行相加或相减并将结果保存在第三个参数中。 #define evutil_timerclear(tvp) /* ... */ #define evutil_timerisset(tvp) /* ... */ evutil_timerclear将一个timeval清空是将其值置为0。evutil_timerisset检查timeval如果timeval的值为非0则该宏返回true否则返回false。 #define evutil_timercmp(tvp, uvp, cmp) evutil_timercmp比较两个timeval并且如果它们之间的相对关系符合关系操作符cmp定义的比较关系的话该宏返回true。比如evutil_timercmp(t1, t2, )意味着“Is t1 t2”。注意不像某些操作系统Libevent的timercmp支持所有的C关系操作符即是, , , !, 和 。 int evutil_gettimeofday(struct timeval *tv, struct timezone*tz); evutil_gettimeofday函数设置tv为当前时间参数tz无用。 struct timeval tv1, tv2, tv3; /* Settv1 5.5 seconds */ tv1.tv_sec 5; tv1.tv_usec 500*1000; /*Set tv2 now */ evutil_gettimeofday(tv2, NULL); /* Settv3 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 thepresent.); if(evutil_timercmp(tv1, tv2, )) /* If tv1 tv2 */ puts(It is no longer the past.); 三Socket API兼容性 由于历史原因Windows从未真正的以良好的兼容性实现伯克利Socket API。下面的函数可以规避这种情况 int evutil_closesocket(evutil_socket_t s); #define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s) 这些函数用来关闭socket在Unix上它就是close函数的别名。在Windows上它调用closesocket。在Windows上不能在socket上调用close也没有其他系统定义closesocket函数。 #define EVUTIL_SOCKET_ERROR() #define EVUTIL_SET_SOCKET_ERROR(errcode) #define evutil_socket_geterror(sock) #define evutil_socket_error_to_string(errcode) 这些宏访问并操作socket错误码。EVUTIL_SOCKET_ERROR返回本线程最近一次的socket操作的全局错误码。evutil_socket_geterror针对某个特定socket做同样的事。在类Unix系统上全局错误码就是errno。EVUTIL_SET_SOCKET_ERROR改变当前的socket错误码类似于在Unix上设置errnoevutil_socket_error_to_string返回给定错误码的字符串描述。类似于Unix上的strerror 之所以需要这些函数是因为Windows没有为socket函数的错误定义errno而是使用函数WSAGetLastError 注意在windows上套接字错误码与标准C错误码errno是不同的。 int evutil_make_socket_nonblocking(evutil_socket_t sock); 对套接字IO的非阻塞设置也不能移植到Windows中。evutil_make_socket_nonblocking函数将一个新的socket描述符由socket或accept返回设置为非阻塞的。在Unix上置为O_NONBLOCK在Windows上置为FIONBIO。 int evutil_make_listen_socket_reuseable(evutil_socket_t sock); 该函数使得关闭一个监听套接字后它使用的地址可以立即被另一个套接字使用。在Unix上是设置SO_REUSEADDR而在Windows上该标志却有其他意义。 int evutil_make_socket_closeonexec(evutil_socket_t sock); 该函数使得操作系统在调用exec之后会关闭该socket描述符。在Unix上是设置FD_CLOEXEC 标志而在Windows上什么也不做。 int evutil_socketpair(int family, int type, int protocol, evutil_socket_t sv[2]); 该函数类似于Unix上的socketpair函数它在两个socket上创建一个相互连接的管道而且可以使用普通的socket io函数。该函数将这两个socket保存在sv[0]和sv[1]中该函数返回0表示成功-1表示失败。 在Windows上该函数仅支持AF_INET协议族SOCK_STREAM类型以及协议0. 注意在某些Windows主机上防火墙软件明确阻止127.0.0.1禁止主机与自身通话的情况下函数可能失败。 四可移植的字符串操作函数 ev_int64_t evutil_strtoll(const char *s, char **endptr, int base) 该函数类似于strtol但是可以处理64位整数。在某些平台上它仅支持十进制。 int evutil_snprintf(char * buf, size_t buflen, const char * format, ...); int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap); 这些snprintf替代函数与标准的snprintf和vsnprintf接口类似。它们返回写入到buffer缓冲区的字节数不包括末尾的NULL字节。这种行为符合C99标准但与Windows上的_snprintf不同它在字符串无法放入缓冲区时返回一个负数。 五区域无关的字符串处理函数 有时当实现基于ASCII的协议时希望能够处理ASCII中字符类型概念上的字符串而不管当前的区域配置。Libevent提供了一些这样的辅助函数。 int evutil_ascii_strcasecmp(const char *str1, const char *str2); int evutil_ascii_strncasecmp(const char *str1, const char *str2, size_t n); 这些函数类似于strcasecmp和strncasecmp但他们仅使用ASCII字符集进行比较而不管当前的区域设置。 六IPV6辅助函数和可移植函数 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); 这些函数类似于标准的inet_ntop和inet_pton函数根据RFC3493中的规定解析和格式化IPv4和IPv6地址。格式化一个IPv4地址调用evutil_inet_ntopaf置为AF_INETsrc指向in_addr结构dst指向一个len长度的字符缓冲区。而对于IPv6地址则af置为AF_INET6src指向in6_addr结构。 要解析一个IPv4或一个IPv6地址调用evutil_inet_pton函数af置为AF_INET或者AF_INET6src中是需要解析的字符串dst指向一个in_addr或者in_addr6结构。 evutil_inet_ntop()失败时返回NULL成功时返回指向dst的指针。evutil_inet_pton()函数成功时返回0失败是返回-1。 int evutil_parse_sockaddr_port(const char *str, struct sockaddr*out, int * outlen); 该函数解析str中的字符串地址并将结果写入到out中。outlen是一个值-结果参数入参时指向一个out长度的整数返回时变为实际使用的字节数。该方法成功时返回0失败是返回-1.它可以处理下面格式的地址 · [ipv6]:port (as in [ffff::]:80) · ipv6 (as in ffff::) · [ipv6] (as in [ffff::]) · ipv4:port (as in 1.2.3.4:80) · ipv4 (as in 1.2.3.4) 如果没有给定port则在sockaddr的结果中port被置为0. int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr*sa2, int include_port); evutil_sockaddr_cmp函数比较两个地址如果sa1在sa2前面则返回负数如果它们相等就返回0如果sa2在sa1前面就返回正数。该函数可以处理AF_INET和AF_INET6地址族而对于其他地址则是未定义的。它保证给出一个所有地址的总排序但是不同的Libevent版本可能会有不同的排序结果。 如果include_port置为false那么如果两个sockaddrs仅在port不同的情况下该函数将他们视为相同的。否则如果include_port置为true则会视为不同的。 七结构体可移植函数 #define evutil_offsetof(type, field) /* ... */ 类似于标准的offsetof宏该宏返回field域在type中的偏移字节。 八安全的随机数生成器 很多应用都需要一个难以预测的随机数源来保证它们的安全性。 void evutil_secure_rng_get_bytes(void * buf, size_t n); 该接口将n个字节的随机数据填充到buf中。如果平台提供了arc4random函数则Libevent会使用该函数。否则的话Libevent使用自己实现的arc4random函数。种子则来自操作系统的熵池entropy poolWindows中的CryptGenRandom其他平台中的/dev/urandom int evutil_secure_rng_init(void); void evutil_secure_rng_add_bytes(const char * dat, size_t datlen); 一般不需要手动初始化安全随机数生成器但是如果需要保证它确实成功的初始化可以调用evutil_secure_rng_init()函数。它会seed RNG(随机数生成器)如果还没有seed过并且在成功时返回0。如果返回-1表明Libevent无法在系统上找到好的熵源而且在没有自己初始化时不能安全的使用RNG。 如果程序运行在可能会放弃权限的环境中比如说通过执行chroot()在放弃权限前应该调用evutil_secure_rng_init()。 可以调用evutil_secure_rng_add_bytes()向熵池加入更多随机字节但通常不需要这么做。 http://www.wangafu.net/~nickm/libevent-book/Ref5_evutil.html 转载于:https://www.cnblogs.com/gqtcgq/p/7247257.html