IP地址和域名之间的转换

一、引言

域名,简单来理解就是我们平常说的网址。比如登录某度买假药时,会在IE浏览器的地址栏输入www.baidu.com,这里我们输入的就是百度的域名。而实际上我们在互联网中要找到某个网站,是需要这个网站的IP地址的,因为在网络中IP地址就是一台主机的联系地址,而通过域名寻找主机时,就需要先将域名转换成IP地址,这就是我们通常说的DNS服务器的作用。

二、通过域名获取IP地址

       网络编程中,我们通过gethostbyname函数可以通过域名获取主机信息。所谓主机信息就是网络那头web服务器的信息,其中就包含该服务器的IP地址。gethostbyname的函数原型如下:


 
 
  1. #include <netdb.h>
  2. struct hostent *gethostbyname(const char *name);
它接收的唯一参数就是我们在浏览器中输入的域名,在前面的例子中也就是某度的url:www.baidu.com。而他的返回值是一个hostent类型的指针,该结构体的定义如下:


 
 
  1. struct hostent
  2. {
  3. char* h_name;
  4. char** h_aliases;
  5. int h_addrtype;
  6. int h_length;
  7. char** h_addr_list;
  8. }

h_name,存有官方域名。官方域名代表某一主页,但是一些公司的域名可能并未在官方域名注册。
h_aliases,存有其他域名。可以通过多个域名访问统一主页,同一IP可以绑定多个域名,出了官方域名外还可指定其他域名。这些信息可以通过h_aliases获得。
h_addrtype 保存的是h_addr_list中IP地址的类型。AF_INET表示IPv4类型的地址,AF_INET6表示IPv6类型的地址,这个大家应该很熟悉吧,就是我们在创建socket时采用的协议族类型。
h_length,保存的IP地址的长度。若是IPv4,因是4个字节,该值是4;若是IPv6,保存的是16个字节,该值是16;

h_addr_list,保存的是IP地址的列表。因为同一个域名可能分配给了多个IP地址,以缓解用户访问的压力,所以这里包含了多个IP地址。但是,值得注意的是,这里面保存的并不是字符串类型的IP地址,而是in_addr结构体变量的地址,也就是说h_addr_list实际上保存的是指针(为了兼容后续的IPv6d地址信息的指针,这里面的指针类型是char* ,而非in_addr*),指向了了in_addr结构体对象,而in_addr包含了IP地址信息。如果我们想要把in_addr结构体变成我们熟悉的点分十进制格式的IP地址,可以借助inet_ntoa()函数,用法请参照后面的例子。

        下面是in_addr结构体的定义:


 
 
  1. strcut in_addr
  2. {
  3. in_addr_t s_addr; //32 位的IPv4地址
  4. }

        接下来,是一个gethostbyname使用实例,我们来获取某度的IP地址:


 
 
  1. #include<unistd.h>
  2. #include<arpa/inet.h>
  3. #include<netdb.h>
  4. void error_handling(char *message);
  5. int main(int argc,char* argv[])
  6. {
  7. int i;
  8. struct hostent* host;
  9. if(argc!= 2)
  10. {
  11. printf( "Usage %s <port>",argv[ 0]);
  12. exit( 1);
  13. }
  14. host=gethostbyname(argv[ 1]);
  15. if(!host)
  16. {
  17. error_handling( "gethostbyname error");
  18. }
  19. printf( "official name is %s\n",host->h_name);
  20. for(i= 0;host->h_aliases[i];i++)
  21. {
  22. printf( "Aliases %d: %s\n",i+ 1,host->h_aliases[i]);
  23. }
  24. printf( "Address type: %s\n",
  25. host->h_addrtype==AF_INET? "AF_INET": "AF_INET6");
  26. for(i= 0;host->h_addr_list[i];i++)
  27. {
  28. printf( "IP addr %d: %s \n",i+ 1,
  29. inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
  30. }
  31. return 0;
  32. }
  33. void error_handling(char* message)
  34. {
  35. fputs(message, stderr);
  36. fputc( '\n', stderr);
  37. exit( 0);
  38. }

        结果如下,发现该度设置了两个IP地址,分别是14.215.177.38和14.215.177.37.


        我们在浏览器里可以直接输入ip地址来访问该度:


三、利用IP地址获取域名

        想利用IP地址获取域名,使用gethostbyaddr函数:


 
 
  1. #include <netdb.h>
  2. # #include <sys/socket.h> /* for AF_INET */
  3. struct hostent *gethostbyaddr(const void *addr,
  4. socklen_t len, int type);

addr,指向in_addr结构体变量的指针。通过id地址获取in_addr结构体变量,相信大家都应该猜到了吧,就是inet_addr("14.215.177.37")。
len,输入的IP地址的长度,单位为字节,若是IPv4该值为4,若是IPv6该值为16
type,IP地址的类型,IPv4:AF_INET,IPv6:AF_INET6

        我们再利用上面获得的ip地址获取百度的域名,使用实例如下:


 
 
  1. #include<stdlib.h>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<unistd.h>
  5. #include<arpa/inet.h>
  6. #include<netdb.h>
  7. void error_handling(char *message);
  8. int main(int argc,char* argv[])
  9. {
  10. int i;
  11. struct hostent* host;
  12. struct sockaddr_in addr;
  13. if(argc!= 2)
  14. {
  15. printf( "Usage %s <port>",argv[ 0]);
  16. exit( 1);
  17. }
  18. memset(&addr, 0, sizeof(addr));
  19. addr.sin_addr.s_addr=inet_addr(argv[ 1]);
  20. host=gethostbyaddr(( char*)&addr.sin_addr.s_addr, 4,AF_INET);
  21. if(!host)
  22. {
  23. error_handling( "gethostbyaddr error");
  24. }
  25. printf( "official name is %s\n",host->h_name);
  26. for(i= 0;host->h_aliases[i];i++)
  27. {
  28. printf( "Aliases %d: %s\n",i+ 1,host->h_aliases[i]);
  29. }
  30. printf( "Address type: %s\n",
  31. host->h_addrtype==AF_INET? "AF_INET": "AF_INET6");
  32. for(i= 0;host->h_addr_list[i];i++)
  33. {
  34. printf( "IP addr %d: %s \n",i+ 1,
  35. inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
  36. }
  37. return 0;
  38. }
  39. void error_handling(char* message)
  40. {
  41. fputs(message, stderr);
  42. fputc( '\n', stderr);
  43. exit( 0);
  44. }

        结果:



原文地址:https://blog.csdn.net/hyman_c/article/details/52522606

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Linux C 语言中,可以使用 getaddrinfo 函数将域名转换IP 地址。 具体实现步骤如下: 1. 引入头文件: ``` #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> ``` 2. 定义 getaddrinfo() 函数所需的结构体: ``` struct addrinfo hints, *res; int status; char ipstr[INET6_ADDRSTRLEN]; ``` 3. 初始化 hints 结构体: ``` memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // AF_INET 或 AF_INET6 均可 hints.ai_socktype = SOCK_STREAM; // TCP ``` 4. 调用 getaddrinfo() 函数: ``` status = getaddrinfo("www.example.com", NULL, &hints, &res); ``` 其中 "www.example.com" 是需要转换域名。 5. 遍历返回的地址列表,并将其转换IP 地址: ``` struct addrinfo *p; void *addr; for(p = res; p != NULL; p = p->ai_next) { if (p->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); } else { // IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); } // 将 IP 地址转换为字符串 inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); } ``` 其中,inet_ntop() 函数将 IP 地址转换为字符串形式,ipstr 变量即为转换后的 IP 地址。 6. 释放内存: ``` freeaddrinfo(res); ``` 完整代码如下: ``` #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { struct addrinfo hints, *res; int status; char ipstr[INET6_ADDRSTRLEN]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; status = getaddrinfo("www.example.com", NULL, &hints, &res); if (status != 0) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); exit(1); } struct addrinfo *p; void *addr; for(p = res; p != NULL; p = p->ai_next) { if (p->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); } else { // IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); } inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); printf("IP address: %s\n", ipstr); } freeaddrinfo(res); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值