libevent參考手冊第五章:輔助類型和函數

譯自http://www.wangafu.net/~nickm/libevent-book/Ref5_evutil.html


<event2/util.h>定義了很多在實現可移植應用時有用的函數,libevent內部也使用這些類型和函數。

1 基本類型

1.1 evutil_socket_t

在除Windows之外的大多數地方,套接字是個整數,操作系統按照數值次序進行處理。然而,使用Windows套接字API時,socket具有類型SOCKET,它實際上是個類似指針的句柄,收到這個句柄的次序是未定義的。在Windows中,libevent定義evutil_socket_t類型爲整型指針,可以處理socket()或者accept()的輸出,而沒有指針截斷的風險。

定義

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個類型在2.0.1-alpha版本中引入。

1.2 標準整數類型

落後於21世紀的C系統常常沒有實現C99標準規定的stdint.h頭文件。考慮到這種情況,libevent定義了來自於stdint.h的、位寬度確定(bit-width-specific)的整數類型:

[翻譯]libevent參考手冊第五章:輔助類型和函數

跟C99標準一樣,這些類型都有明確的位寬度。

這些類型由1.4.0-alpha版本引入。MAX/MIN常量首次出現在2.0.4-alpha版本。

1.3 各種兼容性類型

在有ssize_t(有符號的size_t)類型的平臺上,ev_ssize_t定義爲ssize_t;而在沒有的平臺上,則定義爲某合理的默認類型。ev_ssize_t類型的最大可能值是EV_SSIZE_MAX;最小可能值是EV_SSIZE_MIN。(在平臺沒有定義SIZE_MAX的時候,size_t類型的最大可能值是EV_SIZE_MAX)

ev_off_t用於代表文件或者內存塊中的偏移量。在有合理off_t類型定義的平臺,它被定義爲off_t;在Windows上則定義爲ev_int64_t。

某些套接字API定義了socklen_t長度類型,有些則沒有定義。在有這個類型定義的平臺中,ev_socklen_t定義爲socklen_t,在沒有的平臺上則定義爲合理的默認類型。

ev_intptr_t是一個有符號整數類型,足夠容納指針類型而不會產生截斷;而ev_uintptr_t則是相應的無符號類型。

ev_ssize_t類型由2.0.2-alpha版本加入。ev_socklen_t類型由2.0.3-alpha版本加入。ev_intptr_t與ev_uintptr_t類型,以及EV_SSIZE_MAX/MIN宏定義由2.0.4-alpha版本加入。ev_off_t類型首次出現在2.0.9-rc版本。

2 定時器可移植函數

不是每個平臺都定義了標準timeval操作函數,所以libevent也提供了自己的實現。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這些宏分別對前兩個參數進行加或者減運算,將結果存放到第三個參數中。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

清除timeval會將其值設置爲0。evutil_timerisset宏檢查timeval是否已經設置,如果已經設置爲非零值,返回ture,否則返回false。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

evutil_timercmp宏比較兩個timeval,如果其關係滿足cmp關係運算符,返回true。比如說,evutil_timercmp(t1,t2,<=)的意思是“是否t1<=t2?”。注意:與某些操作系統版本不同的是,libevent的時間比較支持所有C關係運算符(也就是<、>、==、!=、<=和>=)。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

evutil_gettimeofdy()函數設置tv爲當前時間,tz參數未使用。

示例

[翻譯]libevent參考手冊第五章:輔助類型和函數

除evutil_gettimeofday()由2.0版本引入外,這些函數由1.4.0-beta版本引入。

注意:在1.4.4之前的版本中使用<=或者>=是不安全的。

3 套接字API兼容性

本節由於歷史原因而存在:Windows從來沒有以良好兼容的方式實現Berkeley套接字API。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個接口用於關閉套接字。在Unix中,它是close()的別名;在Windows中,它調用closesocket()。(在Windows中不能將close()用於套接字,也沒有其他系統定義了closesocket())

evutil_closesocket()函數在2.0.5-alpha版本引入。在此之前,需要使用EVUTIL_CLOSESOCKET宏。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這些宏訪問和操作套接字錯誤代碼。EVUTIL_SOCKET_ERROR()返回本線程最後一次套接字操作的全局錯誤號,evutil_socket_geterror()則返回某特定套接字的錯誤號。(在類Unix系統中都是errno)EVUTIL_SET_SOCKET_ERROR()修改當前套接字錯誤號(與設置Unix中的errno類似),evutil_socket_error_to_string()返回代表某給定套接字錯誤號的字符串(與Unix中的strerror()類似)。

(因爲對於來自套接字函數的錯誤,Windows不使用errno,而是使用WSAGetLastError(),所以需要這些函數。)

注意:Windows套接字錯誤與從errno看到的標準C錯誤是不同的。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

用於對套接字進行非阻塞IO的調用也不能移植到Windows中。evutil_make_socket_nonblocking()函數要求一個套接字(來自socket()或者accept())作爲參數,將其設置爲非阻塞的。(設置Unix中的O_NONBLOCK標誌和Windows中的FIONBIO標誌)

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個函數確保關閉監聽套接字後,它使用的地址可以立即被另一個套接字使用。(在Unix中它設置SO_REUSEADDR標誌,在Windows中則不做任何操作。不能在Windows中使用SO_REUSEADDR標誌:它有另外不同的含義(譯者注:多個套接字綁定到相同地址))

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個函數告訴操作系統,如果調用了exec(),應該關閉指定的套接字。在Unix中函數設置FD_CLOEXEC標誌,在Windows上則沒有操作。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個函數的行爲跟Unix的socketpair()調用相同:創建兩個相互連接起來的套接字,可對其使用普通套接字IO調用。函數將兩個套接字存儲在sv[0]和sv[1]中,成功時返回0,失敗時返回-1。

在Windows中,這個函數僅能支持AF_INET協議族、SOCK_STREAM類型和0協議的套接字。注意:在防火牆軟件明確阻止127.0.0.1,禁止主機與自身通話的情況下,函數可能失敗。

除了evutil_make_socket_closeonexec()由2.0.4-alpha版本引入外,這些函數都由1.4.0-alpha版本引入。

4 可移植的字符串操作函數

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個函數與strtol行爲相同,只是用於64位整數。在某些平臺上,僅支持十進制。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這些snprintf替代函數的行爲與標準snprintf和vsnprintf接口相同。函數返回在緩衝區足夠長的情況下將寫入的字節數,不包括結尾的NULL字節。(這個行爲遵循C99的snprintf()標準,但與Windows的_snprintf()相反:如果字符串無法放入緩衝區,_snprintf()會返回負數)

evutil_strtoll()從1.4.2-rc版本就存在了,其他函數首次出現在1.4.5版本中。

5 區域無關的字符串操作函數

實現基於ASCII的協議時,可能想要根據字符類型的ASCII記號來操作字符串,而不管當前的區域設置。libevent爲此提供了一些函數:

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這些函數與strcasecmp()和strncasecmp()的行爲類似,只是它們總是使用ASCII字符集進行比較,而不管當前的區域設置。這兩個函數首次在2.0.3-alpha版本出現。

6 IPv6輔助和兼容性函數

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這些函數根據RFC 3493的規定解析和格式化IPv4與IPv6地址,與標準inet_ntop()和inet_pton()函數行爲相同。要格式化IPv4地址,調用evutil_inet_ntop(),設置af爲AF_INET,src指向in_addr結構體,dst指向大小爲len的字符緩衝區。對於IPv6地址,af應該是AF_INET6,src則指向in6_addr結構體。要解析IP地址,調用evutil_inet_pton(),設置af爲AF_INET或者AF_INET6,src指向要解析的字符串,dst指向一個in_addr或者in_addr6結構體。

失敗時evutil_inet_ntop()返回NULL,成功時返回到dst的指針。成功時evutil_inet_pton()返回0,失敗時返回-1。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個接口解析來自str的地址,將結果寫入到out中。outlen參數應該指向一個表示out中可用字節數的整數;函數返回時這個整數將表示實際使用了的字節數。成功時函數返回0,失敗時返回-1。函數識別下列地址格式:

[ipv6]:端口號(如[ffff::]:80)

ipv6(如ffff::)

[ipv6](如[ffff::])

ipv4:端口號(如1.2.3.4:80)

ipv4(如1.2.3.4)

如果沒有給出端口號,結果中的端口號將被設置爲0。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

evutil_sockaddr_cmp()函數比較兩個地址,如果sa1在sa2前面,返回負數;如果二者相等,則返回0;如果sa2在sa1前面,則返回正數。函數可用於AF_INET和AF_INET6地址;對於其他地址,返回值未定義。函數確保考慮地址的完整次序,但是不同版本中的次序可能不同。

如果include_port參數爲false,而兩個地址只有端口號不同,則它們被認爲是相等的。否則,具有不同端口號的地址被認爲是不等的。

除evutil_sockaddr_cmp()在2.0.3-alpha版本引入外,這些函數在2.0.1-alpha版本中引入。

7 結構體可移植性函數

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

跟標準offsetof宏一樣,這個宏返回從type類型開始處到field字段的字節數。

這個宏由2.0.1-alpha版本引入,但2.0.3-alpha版本之前是有bug的。

8 安全隨機數發生器

很多應用(包括evdns)爲了安全考慮需要很難預測的隨機數。

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

這個函數用隨機數據填充buf處的n個字節。

如果所在平臺提供了arc4random(),libevent會使用這個函數。否則,libevent會使用自己的arc4random()實現,種子則來自操作系統的熵池(entropy pool)(Windows中的CryptGenRandom,其他平臺中的/dev/urandom)

接口

[翻譯]libevent參考手冊第五章:輔助類型和函數

不需要手動初始化安全隨機數發生器,但是如果要確認已經成功初始化,可以調用evutil_secure_rng_init()。函數會播種RNG(如果沒有播種過),並在成功時返回0。函數返回-1則表示libevent無法在操作系統中找到合適的熵源(source of entropy),如果不自己初始化RNG,就無法安全使用RNG了。

如果程序運行在可能會放棄權限的環境中(比如說,通過執行chroot()),在放棄權限前應該調用evutil_secure_rng_init()。

可以調用evutil_secure_rng_add_bytes()向熵池加入更多隨機字節,但通常不需要這麼做。

這些函數是2.0.4-alpha版本引入的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章