• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

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

                轉自
            http://blog.sina.com.cn/s/blog_56dee71a0100qo9t.html


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

            基本類型

            1.1 evutil_socket_t

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

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

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

            1.2 標準整數類型

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




            跟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版本。

            定時器可移植函數

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

            接口

            #define evutil_timeradd(tvp, uvp, vvp) /*  */
            #define evutil_timersub(tvp, uvp, vvp) /*  */

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

            接口

            #define evutil_timerclear(tvp) /*  */
            #define evutil_timerisset(tvp) /*  */

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

            接口

            #define evutil_timercmp(tvp, uvp, cmp)

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

            接口

            int evutil_gettimeofday(struct timeval *tv, struct timezone *tz);

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

            示例

            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.");

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

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

            套接字API兼容性

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

            接口

            int evutil_closesocket(evutil_socket_t s);

            #define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s)

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

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

            接口

            #define EVUTIL_SOCKET_ERROR()
            #define EVUTIL_SET_SOCKET_ERROR(errcode)
            #define evutil_socket_geterror(sock)
            #define evutil_socket_error_to_string(errcode)

            這些宏訪問和操作套接字錯誤代碼。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錯誤是不同的。

            接口

            int evutil_make_socket_nonblocking(evutil_socket_t sock);

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

            接口

            int evutil_make_listen_socket_reuseable(evutil_socket_t sock);

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

            接口

            int evutil_make_socket_closeonexec(evutil_socket_t sock);

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

            接口

            int evutil_socketpair(int family, int type, int protocol,
                    evutil_socket_t sv[
            2]);

            這個函數的行為跟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版本引入。

            可移植的字符串操作函數

            接口

            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接口相同。函數返回在緩沖區足夠長的情況下將寫入的字節數,不包括結尾的NULL字節。(這個行為遵循C99的snprintf()標準,但與Windows的_snprintf()相反:如果字符串無法放入緩沖區,_snprintf()會返回負數)

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

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

            實現基于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字符集進行比較,而不管當前的區域設置。這兩個函數首次在2.0.3-alpha版本出現。

            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);

            這些函數根據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。

            接口

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

            這個接口解析來自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。

            接口

            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地址;對于其他地址,返回值未定義。函數確保考慮地址的完整次序,但是不同版本中的次序可能不同。

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

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

            結構體可移植性函數

            接口

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

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

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

            安全隨機數發生器

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

            接口

            void evutil_secure_rng_get_bytes(void *buf, size_t n);

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

            如果所在平臺提供了arc4random(),libevent會使用這個函數。否則,libevent會使用自己的arc4random()實現,種子則來自操作系統的熵池(entropy pool)(Windows中的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()。函數會播種RNG(如果沒有播種過),并在成功時返回0。函數返回-1則表示libevent無法在操作系統中找到合適的熵源(source of entropy),如果不自己初始化RNG,就無法安全使用RNG了。

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

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

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


            久久伊人中文无码| 久久WWW免费人成—看片| 麻豆av久久av盛宴av| 四虎国产精品成人免费久久| 亚洲欧美精品一区久久中文字幕| 亚洲欧美国产精品专区久久| 久久精品人人槡人妻人人玩AV| 久久e热在这里只有国产中文精品99| 欧美午夜A∨大片久久| 77777亚洲午夜久久多喷| 久久婷婷色综合一区二区| 伊人久久综合成人网| 97久久精品人人做人人爽| 久久天天躁狠狠躁夜夜不卡| 久久久久久久99精品免费观看| 综合久久一区二区三区| 久久香蕉一级毛片| 久久精品国产亚洲AV无码娇色| 久久久无码精品亚洲日韩软件| 欧美大香线蕉线伊人久久| 亚洲欧美久久久久9999| 99久久免费只有精品国产| 久久久老熟女一区二区三区| 狠狠色丁香久久婷婷综合_中| 久久成人影院精品777| 日韩精品久久无码人妻中文字幕| 久久综合成人网| 国产亚洲精久久久久久无码AV| 国产精品久久国产精麻豆99网站| 午夜精品久久久久久中宇| 精品久久久久久国产| 久久久久国产精品嫩草影院| 亚洲欧美精品一区久久中文字幕 | 久久露脸国产精品| 久久精品夜色噜噜亚洲A∨| 99久久婷婷国产综合精品草原| 久久se精品一区精品二区| 精品久久久久久亚洲精品| 狠狠色婷婷久久一区二区三区| 久久婷婷五月综合97色| 国产精品视频久久久|