亚洲成精品动漫久久精久,九九在线精品视频播放,黄色成人免费观看,三级成人影院,久碰久,四虎成人欧美精品在永久在线

掃一掃
關(guān)注微信公眾號(hào)

Apache源代碼全景分析:網(wǎng)絡(luò)地址處理 (4)
2006-06-14   

對(duì)于非EAI_SYSTEM錯(cuò)誤碼,APR并不能直接返回。正如第一章所說(shuō),APR中對(duì)于apr_status_t返回碼有自己的布局和規(guī)則,因此這些錯(cuò)誤碼必須轉(zhuǎn)換至APR返回碼。EAI_XXXX錯(cuò)誤碼的起始偏移是APR_OS_START_EAIERR,因此返回值實(shí)際上是rc+APR_OS_START_EAIERR。不過(guò)在一些平臺(tái)上比如glibc,為了防止和h_errno的值沖突,系統(tǒng)將使用EAI_XXXX的負(fù)值, 這正是上面的代碼w的原因。

上面的代碼有一個(gè)假設(shè)前提,就是系統(tǒng)中必須提供getnameinfo()函數(shù)。但是由于getnameinfo()是比較新的一個(gè)函數(shù),并不是每個(gè)操作系統(tǒng)平臺(tái)都支持該函數(shù)。目前大部分Ipv4平臺(tái)上不過(guò)都提供了gethostbyaddr()函數(shù),通過(guò)該函數(shù)也能完成從主機(jī)地址到主機(jī)名稱(chēng)的轉(zhuǎn)換,不過(guò)該函數(shù)僅僅支持Ipv4協(xié)議,不支持Ipv6協(xié)議。具體的代碼如下所示:

#else

#if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) &&

defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS)

#ifdef GETHOSTBYNAME_R_HOSTENT_DATA

struct hostent_data hd;

#else

char tmp[GETHOSTBYNAME_BUFLEN];

#endif

int hosterror;

struct hostent hs, *hptr;

#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)

/* AIX, HP/UX, D/UX et alia */

gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, u

sizeof(struct in_addr), AF_INET, &hs, &hd);

hptr = &hs;

#else

#if defined(GETHOSTBYNAME_R_GLIBC2)

/* Linux glibc2+ */

gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, v

sizeof(struct in_addr), AF_INET,

&hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror);

#else

/* Solaris, Irix et alia */

hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, w

sizeof(struct in_addr), AF_INET,

&hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror);

#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */

if (!hptr) {

*hostname = NULL;

return hosterror + APR_OS_START_SYSERR;

}

#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */

#else

struct hostent *hptr;

hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr, x

sizeof(struct in_addr), AF_INET);

#endif

if (hptr) {

*hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, hptr->h_name);

return APR_SUCCESS;

}

*hostname = NULL;

#if defined(WIN32)

return apr_get_netos_error();

#elif defined(OS2)

return h_errno;

#else

return h_errno + APR_OS_START_SYSERR;

#endif

#endif

函數(shù)中眾多的預(yù)定義讓人眼花繚亂。不過(guò)最主要的預(yù)定義處理還在于對(duì)gethostbyaddr()函數(shù)的調(diào)用。從上面的代碼中可以看出,gethostbyaddr有一個(gè)函數(shù)變形gethostbyaddr_r,而且不同平臺(tái)下的gethostbyaddr_t函數(shù)的參數(shù)也不相同,要了解詳細(xì)的原因,必須了解一些函數(shù)可重入的概念。

所謂可重入函數(shù)是指一個(gè)可以被多個(gè)任務(wù)調(diào)用的函數(shù),任務(wù)在調(diào)用時(shí)候不必?fù)?dān)心數(shù)據(jù)會(huì)出錯(cuò);通常情況下下面的函數(shù)是不可重入的:

(1)、函數(shù)體內(nèi)使用了靜態(tài)的數(shù)據(jù)結(jié)構(gòu);

(2)、函數(shù)體內(nèi)調(diào)用了malloc()或者free()函數(shù);

(3)、函數(shù)體內(nèi)調(diào)用了標(biāo)準(zhǔn)I/O函數(shù)。

通常情況下,在一個(gè)UNIX進(jìn)程中發(fā)生重入問(wèn)題的條件是:從主程序中和某個(gè)信號(hào)處理函數(shù)中同時(shí)調(diào)用某個(gè)不可重入函數(shù).。另外在多線程應(yīng)用中也會(huì)出現(xiàn)函數(shù)重入的問(wèn)題。不幸的是由于歷史的原因,我們經(jīng)常使用的gethostbyaddr也是一個(gè)不可重入的函數(shù),因?yàn)樗鼈兌挤祷刂赶蛲粋€(gè)靜態(tài)結(jié)構(gòu)的指針。關(guān)于gethostbyaddr的重入問(wèn)題,《Unix網(wǎng)絡(luò)編程 第一卷:套接口API》中文版第二版的第207頁(yè)中有一段描述,摘抄如下:

不幸的是,重入問(wèn)題比他表面看起來(lái)更要嚴(yán)重。首先,關(guān)于gethostbyname和gethostbyaddr的重入問(wèn)題無(wú)標(biāo)準(zhǔn)可循。POSIX規(guī)范聲明這兩個(gè)函數(shù)不必是可重入的。Unix98只說(shuō)這兩個(gè)函數(shù)必須是線程安全的。

其次,關(guān)于_r函數(shù)也沒(méi)有標(biāo)準(zhǔn)可循。Solaris 2.X,Digital Unix 4.0和HP-UX 10.30都提供了可重入版本的gethostbyaddr_r函數(shù),不過(guò)它們的參數(shù)并不相同,不同版本的gethostbyaddr_r函數(shù)原型如下表所示:

操作系統(tǒng)平臺(tái) 函數(shù)原型

solaris struct hostent* gethostbyaddr_r(const char *addr, int len, int type,

struct hostent *result, char *buf, int buflen, int * h_errnop);

AIX,HP-UX,Digital Unix int gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result,

struct hostent_data *buffer);

Linux glibc2+ int gethostbyaddr_r(const char *addr,int len, int type,struct hostent *result,

char* buf, int buflen, struct hostent *hs, int* h_errnop);

大部分gethostbyaddr_r函數(shù)的前四個(gè)參數(shù)都相同,第一個(gè)是需要轉(zhuǎn)換的地址;第二個(gè)地址的字節(jié)大小,用sizeof(struct in_addr)表示;第三個(gè)是需要轉(zhuǎn)換地址的協(xié)議族,或者是AF_INET,或者是AF_INET6;第四個(gè)則是描述主機(jī)的hostent結(jié)構(gòu)。區(qū)別通常在后幾個(gè)參數(shù):

對(duì)于Solaris,Irix等操作系統(tǒng)而言,后面還需要三個(gè)額外的參數(shù),buf是由調(diào)用者分配的并且大小為buflen的緩沖區(qū),該緩沖區(qū)用于存放規(guī)范主機(jī)名稱(chēng),別名指針數(shù)組,各個(gè)別名字符串,地址指針數(shù)組以及各個(gè)實(shí)際地址。如果初出錯(cuò),錯(cuò)誤碼通過(guò)h_errnop指針?lè)祷兀⒁獠皇俏覀兺ǔKf(shuō)的h_errno返回。

對(duì)于AIX,HP-UX,Digital Unix等平臺(tái)而言,后面的三個(gè)參數(shù)則被組合為一個(gè)新的數(shù)據(jù)結(jié)構(gòu)hostent_data,指向該結(jié)構(gòu)的指針構(gòu)成本函數(shù)的第三個(gè)和最后一個(gè)參數(shù)。Apache中默認(rèn)的緩沖區(qū)大小為GETHOSTBYNAME_BUFLEN,即512字節(jié)。

對(duì)于Linux glibc2+而言,gethostbyaddr_r的參數(shù)與前兩者又存在一定的差異,它共計(jì)有八個(gè)參數(shù),與Solaris平臺(tái)相比多了struct hostent* hs參數(shù)。

如果操作系統(tǒng)平臺(tái)不支持可重入的gethostaddr_r函數(shù),那么只能使用不可重入的gethostbyaddr函數(shù),如x所示。

返回的主機(jī)名稱(chēng)保存在hostent結(jié)構(gòu)中,如果查詢成功,從hostname參數(shù)中返回即可。

9.1.3.3 IP地址解析

APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr,

char **scope_id,

apr_port_t *port,

const char *str,

apr_pool_t *p);

熱詞搜索:

上一篇:Apache源代碼全景分析:網(wǎng)絡(luò)地址處理 (3)
下一篇:排除使用路由器后無(wú)法使用VPN的故障

分享到: 收藏