- 英文小冊原文位址:beej.us/guide/bgnet…
- 作者:Beej
- 中文翻譯位址:www.chanmufeng.com/posts/netwo…
根據主機名擷取IP位址,或者相反。
函數原型
#include <sys/socket.h>
#include <netdb.h>
struct hostent *gethostbyname(const char *name); // DEPRECATED!
struct hostent *gethostbyaddr(const char *addr, int len, int type);
說明
請注意:這兩個函數已經由 getaddrinfo() 與 getnameinfo() 取而代之!實際上,gethostbyname() 無法在 IPv6 中正常運作。
這些函數可以轉換 host name 與 IP addresse。例如:你可以用
gethostbyname()
取得其 IP address,并儲存在
struct in_addr
。
反之,如果你有一個
struct in_addr
或
struct in6_addr
,你可以用
gethostbyaddr()
得到 hostname。
gethostbyaddr()
與 IPv6 相容,但是你最好使用新的
getnameinfo()
代替它。
(如果你有一個點分十進制格式的IP位址,你想要查詢它的 hostname,你在使用
getaddrinfo()
時最好要搭配
AI_CANONNAME
辨別)。
gethostbyname()
接收一個類似 "www.chanmufeng.com" 的字串,然後傳回一個
struct hostent
,裡面包含了超多的資料,包括了 IP address(其它的資訊包括官方的 host name、一連串的别名、位址類型、位址長度、以及位址清單。這是個通用的資料結構,在特定的用途上使用起來也很友善)。
在
gethostbyaddr()
代入一個
struct in_addr
或
struct in6_addr
,然後就會傳回給你一個相對應的 host name(如果有的話),它的作用和
gethostbyname()
正好相反。至于參數,
addr
是一個
char*
,你實際上想要用一個指向
struct in_addr
的指針;
len
應該被設定成
sizeof(struct in_addr)
,而
type
應為
AF_INET
。
是以這個
struct hostent
會傳回什麼呢?它有許多字段,包含 host 的相關資料。
字段 | 描述 |
char *h_name | 主機的規範(official、canonical)名字 |
char **h_aliases | 可以使用數組通路的别名清單,最後一個元素為NULL |
int h_addrtype | 結果的位址類型,出于我們的目的,它實際上應該是AF_INET。 |
int length | 以位元組為機關的位址長度,對于IP(版本4)位址為4。 |
char **h_addr_list | 此主機的IP位址清單。雖然這是一個char**,但它實際上是一個僞裝的structin_addr *s數組。最後一個數組元素為NULL。 |
h_addr | h_addr_list[0]的常用别名。如果你隻是想要此主機的任何舊IP位址(是的,它們可以有多個),請使用此字段。 |
傳回值
例子
// THIS IS A DEPRECATED METHOD OF GETTING HOST NAMES
// use getaddrinfo() instead!
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int i;
struct hostent *he;
struct in_addr **addr_list;
if (argc != 2) {
fprintf(stderr,"usage: ghbn hostname\n");
return 1;
}
if ((he = gethostbyname(argv[1])) == NULL) { // get the host info
herror("gethostbyname");
return 2;
}
// print information about this host:
printf("Official name is: %s\n", he->h_name);
printf(" IP addresses: ");
addr_list = (struct in_addr **)he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++) {
printf("%s ", inet_ntoa(*addr_list[i]));
}
printf("\n");
return 0;
}
// THIS HAS BEEN SUPERCEDED
// use getnameinfo() instead!
struct hostent *he;
struct in_addr ipv4addr;
struct in6_addr ipv6addr;
inet_pton(AF_INET, "192.0.2.34", &ipv4addr);
he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
printf("Host name: %s\n", he->h_name);
inet_pton(AF_INET6, "2001:db8:63b3:1::beef", &ipv6addr);
he = gethostbyaddr(&ipv6addr, sizeof ipv6addr, AF_INET6);
printf("Host name: %s\n", he->h_name);