网络进程间通信函数一

来源:互联网 发布:刘备是汉室宗亲吗 知乎 编辑:程序博客网 时间:2024/05/01 13:09

inet_ntop与 inet_pton:

转自:点击打开链接 http://www.cnblogs.com/s7vens/archive/2011/12/12/2284964.html

Linux下这2个IP地址转换函数,可以在将IP地址在“点分十进制”和“整数”之间转换
而且,inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6。算是比较新的函数了。

inet_pton函数原型如下[将"点分十进制" -> "整数"]

#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>int inet_pton(int af, const char *src, void *dst);//这个函数转换字符串到网络地址,第一个参数af是地址族,转换后存在dst中

inet_pton是inet_addr的扩展,支持的多地址族有下列:
af = AF_INET
src为指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函数将该地址转换为in_addr的结构体,并复制在*dst中
af = AF_INET6
src为指向IPV6的地址,函数将该地址转换为in6_addr的结构体,并复制在*dst中
如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和src格式不对,函数将返回0。

inet_ntop函数原型如下[将"点分十进制" -> "整数"]

#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);//这个函数转换网络二进制结构到ASCII类型的地址,参数的作用和上面相同,只是多了一个参数socklen_t cnt,//他是所指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC

下面是例程:

复制代码
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>int main (void){  char IPdotdec[20]; // 存放点分十进制IP地址  struct in_addr s;  // IPv4地址结构体  // 输入IP地址  printf("Please input IP address: ");  scanf("%s", &IPdotdec);  // 转换  inet_pton(AF_INET, IPdotdec, (void *)&s);  printf("inet_pton: 0x%x\n", s.s_addr); // 注意得到的字节序  // 反转换  inet_ntop(AF_INET, (void *)&s, IPdotdec, 16);  printf("inet_ntop: %s\n", IPdotdec);}
gethostent:

先说说/etc/host配置文件

1,/etc/hosts,主机名何ip配置文件。
hosts---The static table lookup for host name(主机名查询静态表)

linux 的/etc/hosts是配置ip地址和其对应主机名的文件,这里可以记录本机的或其他主机的ip及其对应主机名。
不同的linux版本,这个配置文件也可能不同。比如Debian的对应文件时/etc/hostname。

2,配置文件的用途;

这个文件可以配置主机IP及其对应的主机名,对于服务器类型的linux系统其作用还试不可忽略的。
在局域网或者是INTERNET上,每台主机都由一个IP地址,它区分每台主机,并可以根据IP进行通讯。但IP地址不方便记忆,所有又有了域名。在一个局域网中,每台机器都有一个主机名,用于区分主机,便于相互访问。

linux主机名的相关配置文件就是/etc/hosts;这个文件告诉主机那些域名对应那些ip,哪些主机名对应哪些ip:
比如文件中有这样的定义
192.168.1.100    linumu100    test100
假设192.168.1.100是一台网站服务器,在网页中输入http://linumu100或http://test1000就会打开192.168.1.100的网页。

通常情况下这个文件首先记录了本机的ip和主机名:
172.0.0.1    localhost.localdomain    localhost

3,配置文件格式说明

一般/etc/hosts的内容一般有如下类似内容:
127.0.0.1   localhost.localdomain    localhost
192.168.1.100    linumu100.com    linumu100
192.168.1.120   ftpserver    ftp120

一般情况下hosts文件的每行尾一个主机,每行由三部分组成,每个部分由空格隔开。

第一部分:网络IP地址;
第二部分:主机名或域名;
第三部分:主机名别名;

当然每行也可以是两部分,即主机IP地址和主机名。

主机名(hostname)和域名(domain)的区别:
主机名通常在局域网内使用,通过hosts文件,主机名就被解析到对应IP;
域名通常在INTERNET上使用,但如果本机不想使用internet上的域名解析,这时就可以更改hosts文件,加入自己的域名解析。

4,hosts文件可以帮助解决哪些问题

4.1远程登录linux主机过慢问题
有时候客户端想要远程登录一台linux主机,但每次登录输入密码后都会等很长一段时间才会进入,这是因为linux主机在返回信息时需要解析IP,如果在linux主机的hosts文件事先就加入客户端的IP地址,这时再从客户端远程登录linux就会很快。
4.2 双机互联
当两台主机只是双机互连时,这时两台主机都需要设置自己的ip,同时在对方的hosts文件里加入自己的ip和主机名。

5,主机名修改工具hostname;

hostname---show or set the system's host name

显示主机名:
#hostname 
显示主机IP:
#hostname -i
临时设置主机名:
#hostname test100

1、原理:查询 /etc/hosts 等文件及 DNS or NIS 服务器
The  domain  name  queries carried out by gethostbyname() and gethostbyaddr() use a combination of any or all of the name server named(8), a broken out line from /etc/hosts, and the Network Information Service (NIS or YP), depending upon the contents of the order line in /etc/host.conf.  The default  action  is  to  query named(8), followed by /etc/hosts.(ubuntu man page)

The network configuration information returned by these functions can be kept in a number of places. They can be kept in static files (/etc/hosts, /etc/services, etc.), or they can be managed by a name service, such as DNS (Domain Name System) or NIS (Network Information Service). 

2、说明:
1) gethostbyname*() 和 gethostbyaddr*() 已经过时,用 getaddrinfo() 和 getnameinfo() 替代
The  gethostbyname*()  and  gethostbyaddr*()  functions  are  obsolete. Applications should use getaddrinfo(3) and getnameinfo(3) instead.
POSIX.1-2001 specifies gethostbyname(), gethostbyaddr(), sethostent(), endhostent(), gethostent(), and h_errno;
gethostbyname(), gethostbyaddr(), and h_errno are marked  obsolescent  in  that standard.
POSIX.1-2008 removes the specifications of gethostbyname(), gethostbyaddr(), and h_errno, recommending the use of getaddrinfo(3) and getnameinfo(3) instead.
(ubuntu man page)

The gethostbyname and gethostbyaddr functions only support IPv4. The API for resolving IPv6 addresses went through several iterations, as will be described in Section 11.20; the final result is the getaddrinfo function.(UNIX Network Programming Volume 1, Third Edition )

2) 返回只想静态数据区的指针
The value that gethostbyname returns points to a static structure within the library. You must copy the information from this structure before you make further gethostbyname , gethostbyaddr , or gethostent calls.
(ubuntu man page)

3) http://beej.us/guide/bgnet/output/html/multipage/gethostbynameman.html


4) gethostent(): gets the next entry in the host file, 即每次获取下一个entry, 所以编写程序是通常都用一个 while 循环来获取所有 entry

[cpp] view plaincopy
  1. ----------struct hostent  

[cpp] view plaincopy
  1. struct hostent  
  2. {  
  3.   char *h_name;         /* Official name of host.  */  
  4.   char **h_aliases;     /* Alias list.  */  
  5.   int h_addrtype;       /* Host address type.  */  
  6.   int h_length;         /* Length of address.  */  
  7.   char **h_addr_list;       /* List of addresses from name server.  */  
  8. #if defined __USE_MISC || defined __USE_GNU  
  9. # define    h_addr  h_addr_list[0] /* Address, for backward compatibility.*/  
  10. #endif  
  11. };  

----------gethostent()

[cpp] view plaincopy
  1. /** 
  2.  * gethostent() 
  3.  * OS: Ubuntu 11.04 Server 
  4.  */  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <netdb.h>  
  8. #include <arpa/inet.h>    // inet_ntop()  
  9.   
  10. static void printhost(struct hostent *host);  
  11.   
  12. int  
  13. main(int argc, char *argv[])  
  14. {  
  15.     struct hostent *host = NULL;  
  16.     sethostent(1);  
  17.     while( (host = gethostent()) != 0 )  
  18.     {  
  19.         printhost(host);  
  20.         printf("\n");  
  21.     }  
  22.     endhostent();  
  23.     return EXIT_SUCCESS;  
  24. }  
  25. static void printhost(struct hostent *host)  
  26. {  
  27.     char **aliases = NULL;  
  28.     char **addr_list = NULL;  
  29.     char addr_p[INET_ADDRSTRLEN];   // IPv4  
  30.       
  31.     /* print host name and aliases */  
  32.     printf("hostname: %s\n", host->h_name);  
  33.     for(aliases = host->h_aliases; *aliases; aliases++)  
  34.     {  
  35.         printf("alternate name: %s\n", *aliases);  
  36.     }  
  37.       
  38.     /* print address type and length */  
  39.     if(host->h_addrtype == AF_INET)  
  40.     {  
  41.         printf("address type: AF_INET\n");  
  42.     }  
  43.     else  
  44.     {  
  45.         printf("Not an IPv4 address.\n");  
  46.     }  
  47.     printf("address length: %d\n", host->h_length);  
  48.       
  49.     /* print address list */  
  50.     //printf("%d\n", sizeof(*(host->h_addr_list)));  
  51.     printf("%x\n", *(int *)(*(host->h_addr_list)));  
  52.     for(addr_list = host->h_addr_list; *addr_list; addr_list++)  
  53.     {  
  54.         printf("address: %s\n", inet_ntop(host->h_addrtype, *addr_list, addr_p, INET_ADDRSTRLEN));  
  55.     }  
  56. }  
  57. /* 
  58. hostname: localhost 
  59. address type: AF_INET 
  60. address length: 4 
  61. 100007f 
  62. address: 127.0.0.1 
  63.  
  64. hostname: Ubuntu-Server.localdomain 
  65. alternate name: Ubuntu-Server 
  66. address type: AF_INET 
  67. address length: 4 
  68. 101007f 
  69. address: 127.0.1.1 
  70.  
  71. hostname: ip6-localhost 
  72. alternate name: ip6-loopback 
  73. address type: AF_INET 
  74. address length: 4 
  75. 100007f 
  76. address: 127.0.0.1 
  77. */  
Q: 为什么只能得到 127.0.0.1 这个IP?

A: /etc/hosts 文件内容如下:

[cpp] view plaincopy
  1. 127.0.0.1       localhost  
  2. 127.0.1.1       Ubuntu-Server.localdomain       Ubuntu-Server  
  3. ...  
这跟这组函数的工作原理有关


----------gethostbyname()

[cpp] view plaincopy
  1. /** 
  2.  * gethostbyname() 
  3.  * OS: Ubuntu 11.04 Server 
  4.  */  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <netdb.h>  
  8. #include <arpa/inet.h>    /* inet_ntop() */  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     struct hostent *h_ent = NULL;  
  13.     char addr_p[INET_ADDRSTRLEN];  
  14.     char **addr_list = NULL;  
  15.       
  16.     /* Verify a "hostname" parameter was supplied */  
  17.     if(argc != 2)  
  18.     {  
  19.         printf("please input the hostname.\n");  
  20.         exit(EXIT_FAILURE);  
  21.     }  
  22.       
  23.     /* call gethostbyname() with a host name. gethostbyname() returns a pointer to a hostent struct or NULL. */  
  24.     h_ent = gethostbyname(argv[1]);  
  25.     if(h_ent == NULL)  
  26.     {  
  27.         printf("%s was not resolved.\n", argv[1]);  
  28.         exit(EXIT_FAILURE);  
  29.     }  
  30.       
  31.     for(addr_list = h_ent->h_addr_list; *addr_list; addr_list++)  
  32.     {  
  33.         inet_ntop(AF_INET, *(addr_list), addr_p, INET_ADDRSTRLEN);  
  34.         printf("hostname: %s, was resolved to: %s\n", argv[1], addr_p);  
  35.     }  
  36.   
  37.     return 0;  
  38. }  
  39. /* 
  40. $ ./a.out baidu.com 
  41. hostname: baidu.com, was resolved to: 220.181.111.85 
  42. hostname: baidu.com, was resolved to: 220.181.111.86 
  43. hostname: baidu.com, was resolved to: 123.125.114.144 
  44.  
  45. add a line in /etc/hosts: 
  46. 111.111.111.111 baidu.com 
  47. $ ./a.out baidu.com 
  48. hostname: baidu.com, was resolved to: 111.111.111.111 
  49. */  
Q: 为什么修改 /etc/hosts 之后出现上述结果?

A: The  domain  name  queries carried out by gethostbyname() and gethostbyaddr() use a combination of any or all of the name server named(8), a broken out line from /etc/hosts, and the Network Information Service (NIS or YP), depending upon the contents of the order line in /etc/host.conf. (ubuntu man page)

/etc/host.conf 文件内容如下:

[cpp] view plaincopy
  1. # The "order" line is only used by old versions of the C library.  
  2. order hosts,bind  
  3. multi on  
hosts 文件优先


----------gethostbyaddr()

[cpp] view plaincopy
  1. /** 
  2.  * gethostbyaddr() 
  3.  * OS: Ubuntu 11.04 Server 
  4.  */  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <netdb.h>  
  8. #include <arpa/inet.h>    /* inet_pton() */  
  9.   
  10. int main(int argc, char *argv[])  
  11. {  
  12.     struct hostent *h_ent = NULL;  
  13.     char addr_n[sizeof(struct in_addr)];    // or struct in_addr addr_n;  
  14.     int status;  
  15.       
  16.     /* Verify a "ip address" parameter was supplied */  
  17.     if(argc != 2)  
  18.     {  
  19.         printf("please input the ip address.\n");  
  20.         exit(EXIT_FAILURE);  
  21.     }  
  22.       
  23.     status = inet_pton(AF_INET, argv[1], addr_n);  
  24.     if(status == 0) // invalid format  
  25.     {  
  26.         printf("The format of the ip address is invalid.\n");  
  27.         exit(EXIT_FAILURE);  
  28.     }  
  29.     else if(status == -1)  
  30.     {  
  31.         printf("error: inet_pton\n");  
  32.         exit(EXIT_FAILURE);  
  33.     }  
  34.       
  35.     /* call gethostbyaddr() */  
  36.     h_ent = gethostbyaddr(addr_n, sizeof(struct in_addr), AF_INET);  
  37.     if(h_ent == NULL)  
  38.     {  
  39.         printf("error: gethostbyaddr\n");  
  40.         exit(EXIT_FAILURE);  
  41.     }  
  42.       
  43.     printf("%s was resolved to hostname: %s\n", argv[1], h_ent->h_name);  
  44.       
  45.     return 0;  
  46. }  
  47. /* 
  48. $ ./a.out 220.181.111.85    # baidu.com 
  49. error: gethostbyaddr 
  50.  
  51. add a line in /etc/hosts: 
  52. 111.111.111.111 baidu.com 
  53. $ ./a.out 111.111.111.111 
  54. 111.111.111.111 was resolved to hostname: baidu.com 
  55. */  
0 0
原创粉丝点击