struct hostent結構體
2007-08-22 23:54:25| 分類(lèi): Linux & C |舉報|字號 訂閱
這個(gè)數據結構是這樣的:
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
#define h_addr h_addr_list[0]
這里是這個(gè)數據結構的詳細資料:
struct hostent:
h_name – 地址的正式名稱(chēng)。
h_aliases – 空字節-地址的預備名稱(chēng)的指針。
h_addrtype –地址類(lèi)型; 通常是AF_INET。
h_length – 地址的比特長(cháng)度。
h_addr_list – 零字節-主機網(wǎng)絡(luò )地址指針。網(wǎng)絡(luò )字節順序。
h_addr - h_addr_list中的第一地址。
gethostbyname() 成功時(shí)返回一個(gè)指向結構體 hostent 的指針,或者 是個(gè)空 (NULL) 指針。(但是和以前不同,不設置errno,h_errno 設置錯 誤信息。請看下面的 herror()。) 但是如何使用呢? 這個(gè)函數可不象它看上去那么難用。
這里是個(gè)例子:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
struct hostent *h;
if (argc != 2) { /* 檢查命令行 */
fprintf(stderr,"usage: getip address\n");
exit(1);
}
if ((h=gethostbyname(argv[1])) == NULL) { /* 取得地址信息 */
herror("gethostbyname");
exit(1);
}
printf("Host name : %s\n", h->h_name);
printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)h->h_addr)));
return 0;
}
在使用 gethostbyname() 的時(shí)候,你不能用perror() 打印錯誤信息 (因為 errno 沒(méi)有使用),你應該調用 herror()。
相當簡(jiǎn)單,你只是傳遞一個(gè)保存機器名的字符串(例如 "whitehouse.gov") 給gethostbyname(),然后從返回的數據結構 struct hostent 中獲取信息。 唯一也許讓人不解的是輸出 IP 地址信息。h->h_addr 是一個(gè) char *, 但是 inet_ntoa() 需要的是 struct in_addr。因此,我轉換 h->h_addr 成 struct in_addr *,然后得到數據。
使用這個(gè)東西,首先要包含2個(gè)頭文件:
#include <netdb.h>
#include <sys/socket.h>
struct hostent *gethostbyname(const char *name);
這個(gè)函數的傳入值是域名或者主機名,例如 www.google.com,wpc 等等。
傳出值,是一個(gè)hostent的結構(如下)。如果函數調用失敗,將返回NULL。
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
解釋一下這個(gè)結構:
其中,
char *h_name 表示的是主機的規范名。例如 www.google.com 的規范名其實(shí)是 www.l.google.com 。
char **h_aliases 表示的是主機的別名。 www.google.com 就是google他自己的別名。有的時(shí)候,有的主機可能有好幾個(gè)別名,這些,其實(shí)都是為了易于用戶(hù)記憶而為自己的網(wǎng)站多取的名字。
int h_addrtype 表示的是主機ip地址的類(lèi)型,到底是ipv4(AF_INET),還是ipv6(AF_INET6)
int h_length 表示的是主機ip地址的長(cháng)度
int **h_addr_lisst 表示的是主機的ip地址,注意,這個(gè)是以網(wǎng)絡(luò )字節序存儲的。千萬(wàn)不要直接用printf帶%s參數來(lái)打這個(gè)東西,會(huì )有問(wèn)題的哇。所以到真正需要打印出這個(gè)IP的話(huà),需要調用inet_ntop()。
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) :
這個(gè)函數,是將類(lèi)型為af的網(wǎng)絡(luò )地址結構src,轉換成主機序的字符串形式,存放在長(cháng)度為cnt的字符串中。
這個(gè)函數,其實(shí)就是返回指向dst的一個(gè)指針。如果函數調用錯誤,返回值是NULL。
下面是例程,有詳細的注釋。
#include <netdb.h>
#include <sys/socket.h>
int main(int argc, char **argv)
{
char *ptr,**pptr;
struct hostent *hptr;
char str[32];
/* 取得命令后第一個(gè)參數,即要解析的域名或主機名 */
ptr = argv[1];
/* 調用gethostbyname()。調用結果都存在hptr中 */
if( (hptr = gethostbyname(ptr) ) == NULL )
{
printf("gethostbyname error for host:%s\n", ptr);
return 0; /* 如果調用gethostbyname發(fā)生錯誤,返回1 */
}
/* 將主機的規范名打出來(lái) */
printf("official hostname:%s\n",hptr->h_name);
/* 主機可能有多個(gè)別名,將所有別名分別打出來(lái) */
for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
printf(" alias:%s\n",*pptr);
/* 根據地址類(lèi)型,將地址打出來(lái) */
switch(hptr->h_addrtype)
{
case AF_INET:
case AF_INET6:
pptr=hptr->h_addr_list;
/* 將剛才得到的所有地址都打出來(lái)。其中調用了inet_ntop()函數 */
for(;*pptr!=NULL;pptr++)
printf(" address:%s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
break;
default:
printf("unknown address type\n");
break;
}
return 0;
}