名字和數值地址間進行轉換的函數:gethostbyname和gethostbyaddr在主機名字與IPv4地址之間進行轉換。getservbyname和getservbyport在服務器名字和端口號之間進行轉換。還有兩個協議無關的轉換函數:getaddrinfo和getnameinfo,分別用於主機名字和IP地址之間以及服務名字和端口之間的轉換。shell
1.gethostbyname函數ubuntu
經過傳入域名或者主機名,返回一個指向hostent結構的指針,該結構中含有所查找主機的全部IPv4地址。這個函數的侷限是隻能返回IPv4地址。服務器
#include <netdb.h> struct hostent *gethostbyname(const char *hostname)本函數返回的非空指針指向以下的hostent結構。
struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses */ }
h_name爲正式主機名網絡
h_aliases爲全部的別名dom
h_addrtype爲AF_INETsocket
h_length爲4tcp
h_addr_list爲IPv4地址函數
#include <stdio.h> #include <stdlib.h> #include <netdb.h> #include <sys/socket.h> #define MAX 100 int main(int argc, char **argv) { char *ptr, **pptr; char str[MAX]; struct hostent *hptr; while (--argc > 0) { ptr = *++argv; if ( (hptr = gethostbyname(ptr)) == NULL) { printf("gethostbyname error for host: %s: %s", ptr, hstrerror(h_errno)); continue; } printf("official hostname: %s\n", hptr->h_name); for (pptr = hptr->h_aliases; *pptr != NULL; pptr++) printf("\talias: %s\n", *pptr); switch (hptr->h_addrtype) { case AF_INET: pptr = hptr->h_addr_list; for ( ; *pptr != NULL; pptr++) printf("\taddress: %s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); break; default: printf("unknown address type"); break; } } exit(0); }運行結果:
huangcheng@ubuntu:~$ ./a.out www.a.shifen.com www.baidu.com official hostname: www.a.shifen.com address: 115.239.210.27 address: 115.239.210.26 official hostname: www.a.shifen.com alias: www.baidu.com address: 115.239.210.27 address: 115.239.210.26即百度的正式主機名爲: www.a.shifen.com;域名爲:www.baidu.com
huangcheng@ubuntu:~$ ./a.out www.hikvision.com official hostname: www.hikvision.com address: 223.4.99.235
2.gethostbyaddr函數this
gethostbyaddr函數試圖由一個二進制的IP地址找到相應的主機名,與gethostbyname的行爲恰好相反。spa
#include <netdb.h> struct hostent *gethostbyaddr(const char *addr,socklen_t len,int family);addr參數實際上不是char *類型,而是一個指向存放IPv4地址的某個in_addr結構的指針(注意,這裏不是簡單的字符串, 須要先將字符串形式的IP地址由inet_aton轉化一下 );len參數是這個結構的大小:對於IPv4地址爲4。family參數爲AF_INET。
#include<arpa/inet.h> #include<unistd.h> #include<netdb.h> #include<sys/utsname.h> #include<stdlib.h> #include<stdio.h> int main() { struct hostent *pHost = NULL; char str[100]; in_addr_t addr = inet_addr("192.168.2.103"); pHost = gethostbyaddr((char*)&addr,4,AF_INET); /* struct utsname Name; uname(&Name); pHost = gethostbyname((char*)&Name);*/ printf("official hostname:%s\n",pHost->h_name); char **pAliases = pHost->h_aliases; for(; NULL != *pAliases; pAliases++) printf("aliases:%s\n",*pAliases); char **pAddrlist = NULL; switch(pHost->h_addrtype) { case AF_INET: case AF_INET6: pAddrlist = pHost->h_addr_list; for(; NULL != *pAddrlist; pAddrlist++) printf("address:%s\n",inet_ntop(pHost->h_addrtype,*pAddrlist,str,sizeof(str))); break; default: printf("unknown type\n"); break; } return 0; }運行結果:
huangcheng@ubuntu:~$ ./a.out official hostname:ubuntu.local address:192.168.2.103
3.getservbyname函數
像主機同樣,服務也一般靠名字來認知。若是咱們在程序代碼中經過其名字而不是其端口號來指代一個服務,並且從名字到端口號的映射關係保存在一個文件中(一般是/etc/services),那麼即便端口號發生變更,咱們需需修改的僅僅是/etc/services文件中的某一行,而沒必要從新編譯應用程序。getservbyname函數用於根據給定名字查找相應服務。
#include <netdb.h> struct serven *getservbyname(const char *servname,const char protoname);本函數返回的非空指針指向以下的servent結構:
struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port number */ char *s_proto; /* protocol to use */ }
服務名參數:servname 協議參數:protoname
servent結構中咱們關心的主要字段是端口號。既然端口號是以網絡字節序返回的,把它存放到套接字地址結構時絕對不能調用htons。
本函數的典型調用以下:
struct serven *sptr; sptr = getservbyname("domain","udp"); /*DNS using UDP*/ sptr = getservbyname("ftp","tcp"); /*FTP using TCP */ sptr = getservbyname("ftp",NULL); /*FTP using TCP"*/ sptr = getservbyname("ftp","udp"); /*this call will fail*/
既然FTP僅僅支持TCP,第二個調用和第三個調用等效,第四個調用則會失敗。
4.getservbyport函數
getservbyport函數用於根據給定端口號和可選協議查找相應服務。
#include <netdb.h> struct servent *getserbyport(int port,const char *protoname);
注意:參數port必須爲網絡字節序
本函數的典型調用以下:
struct servent *sptr; sptr = getservbyport(htons(53),"udp"); /* DNS using UDP */ sptr = getservbyport(htons(21),"tcp"); /*FTP using TCP */ sptr = getservbyport(htons(21),NULL); /* FTP using TCP */ sptr = getservbyport(htons(21),"udp"); /* this call will fial */
由於UDP上沒有服務使用端口21,因此最後一個調用將失敗。
必須清楚的是,有些端口號在TCP上用於一種服務,在UDP上卻用於徹底不一樣的另外一個服務。例如:
huangcheng@ubuntu:~$ grep 514 /etc/services shell 514/tcp cmd # no passwords used syslog 514/udp代表端口514在TCP上由rsh命令使用,在UDP上卻由syslog守護進程使用。