当前位置: 首页 > news >正文

《TCP/IP网络编程》(第八章)域名及网络地址

DNS(Domain Name System,域名系统) 是互联网上用于将域名和IP地址相互映射的一个分布式数据库系统。它的主要作用是让人们能够使用易于记忆的域名(如 www.example.com)来访问互联网上的资源,而不需要记住复杂的数字IP地址(如 192.0.2.1)。

1.DNS请求域名IP地址

所有计算机中都记录着默认DNS服务器地址,通过这个默认DNS服务器可以得到相应域名的IP地址信息,下图是请求过程:
在这里插入图片描述
计算机内置的默认DNS服务器并不知道网络上所有域名的IP地址信息,若该DNS服务器无法解析,则会逐级向上询问DNS服务器,如果一直都无法解析,则最终会到达根服务器,它知道该向那个DNS服务器询问,得到IP地址信息后原路返回,然后通过IP地址向目标服务器发送请求。

2.程序编写中需要使用域名吗?

  1. 用户友好性: 域名通常比IP地址更易于记忆和识别,使用域名可以提高用户体验。
  2. 可扩展性: 域名允许在不更改程序代码的情况下更换服务器IP地址,这在服务器迁移或扩展时非常有用。
  3. 负载均衡: 通过域名,可以更容易地实现负载均衡,将请求分发到多个服务器上。
  4. 安全性: 域名可以与SSL/TLS证书结合使用,提供安全的HTTPS连接,保护数据传输的安全。
  5. 易于管理: 使用域名可以简化网络配置和维护,因为域名解析和管理通常比IP地址更简单。

3.利用域名获取IP地址

这里将介绍gethostbyname()getaddrinfo()两种函数,使用这些函数可以通过传递字符串格式的域名,获取IP地址
①Linux系统
gethostbyname()函数是早期的网络编程API,用于将主机名转换为IP地址,只支持IPv4地址,并且返回的是一个静态的hostent结构。

struct hostent *gethostbyname(const char *name);
//成功时返回hostent结构体地址,失败时返回NULL指针
//name表示要查询的域名struct hostent {char    *h_name;       //官方域名char    **h_aliases;   //其他域名,同一IP可以绑定多个域名int     h_addrtype;    //表示主机地址的类型,最常见的是AF_INET,表示IPv4地址。int     h_length;      //表示每个地址的字节长度char    **h_addr_list; //一个指向字符指针数组的指针,数组中的每个元素都指向一个IP地址//因为用户较多的网站会给一个域名分配多个IP,利用多个服务器进行负载均衡
};
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handling(char *message);int main(int argc, char *argv[]){int i;struct hostent *host;if(argc != 2){printf("Usage : %s <addr>\n", argv[0]);exit(1);}// 使用gethostbyname()函数获取主机信息host = gethostbyname(argv[1]);// argv[1]是命令行输入的主机名或IP地址if(!host){error_handling("gethostbyname() error");}// 打印主机的官方名称printf("Official name : %s \n", host->h_name);for(i = 0; host->h_aliases[i]; i++){printf("Aliases %d : %s \n", i+1, host->h_aliases[i]);// 打印主机的所有别名}printf("Address type : %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");for(i=0; host->h_addr_list[i]; i++)// 打印所有IP地址printf("IP addr %d : %s \n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));inet_ntoa(*(struct in_addr*)host->h_addr_list[i]);return 0;}void error_handling(char *msg){fputs(msg, stderr);fputc('\n', stderr);exit(1);
}

在这里插入图片描述

getaddrinfo()函数是一个现代的、可扩展的网络地址解析函数,它支持IPv4和IPv6,这里只给出基本语法

int getaddrinfo(const char *nodename,const char *servname,const struct addrinfo *hints,struct addrinfo **res);
//nodename: 要查询的域名
//servname: 要查询的服务名,可以是NULL,表示使用默认端口。
//hints: 指向addrinfo结构的指针,该结构提供了查询的选项,如地址族(IPv4或IPv6)、套接字类型(如流套接字SOCK_STREAM)、协议类型等。
//res: 函数返回时,指向一个addrinfo结构链表的指针,每个结构包含一个解析后的地址。struct addrinfo {int              ai_flags;      /* 特殊选项标志 */int              ai_family;     /* 地址族(如AF_INET,AF_INET6) */int              ai_socktype;   /* 套接字类型(如SOCK_STREAM) */int              ai_protocol;   /* 协议(如IPPROTO_TCP) */socklen_t        ai_addrlen;    /* 结构ai_addr的长度 */struct sockaddr *ai_addr;       /* 结构ai_addr的指针 */char             *ai_canonname; /* 规范主机名 */struct addrinfo *ai_next;       /* 下一个addrinfo结构的指针 */
};

②Windows系统
gethostbyname()getaddrinfo()两种函数在Windows系统中的语法,和Linux系统中完全相同,这里就不再赘述,直接给出示例代码:

gethostbyname()函数

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void error_handling(char *message);int main(int argc, char *argv[])
{WSADATA wsaData;int i;struct hostent *host;if(argc != 2){printf("Usage : %s <addr>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)error_handling("WSAStartup() error!");host = gethostbyname(argv[1]);if(!host){error_handling("gethostbyname() error!");}printf("Official name : %s \n", host->h_name);for(i = 0; host->h_aliases[i]; i++)printf("Aliases %d : %s \n", i+1, host->h_aliases[i]);printf("Address type : %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");for(i = 0; host->h_addr_list[i]; i++)printf("IP addr %d : %s \n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));WSACleanup();return 0;}void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}

在这里插入图片描述

4.利用IP地址获取域名

这里将介绍gethostbyaddr()getnameinfo()两种函数,使用这些函数可以利用IP地址,获取域名。

①Linux系统
getthostbyaddr()函数是早期的网络编程API,成功时,返回一个指向hostent结构的指针;失败时,返回NULL。可能不是线程安全的,并且在某些系统上可能已被废弃,同样的不支持IPv6

 struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
//addr: 指向IP地址的指针,该地址以网络字节顺序给出。
//len: IP地址的长度,对于IPv4地址通常是sizeof(struct in_addr),对于IPv6地址是sizeof(struct in6_addr)。
//type: 地址类型,对于IPv4地址使用AF_INET,对于IPv6地址使用AF_INET6。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handling(const char *message);int main(int argc, char *argv[]){int i;struct hostent *host;struct sockaddr_in addr;if(argc != 2){printf("Usage : %s <addr>\n", argv[0]);exit(1);}memset(&addr, 0, sizeof(addr));addr.sin_addr.s_addr = inet_addr(argv[1]);host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr), AF_INET);//将IP地址转换为域名if(!host){error_handling("gethost... error");}printf("Official name : %s \n", host->h_name);for(i=0; host->h_aliases[i]; i++){printf("Aliases %d : %s \n", i+1, host->h_aliases[i]);}printf("Address type : %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");for(i=0; host->h_addr_list[i]; i++){printf("IP addr %d : %s \n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));}return 0;}void error_handling(const char *msg){fputs(msg, stderr);fputc('\n', stderr);exit(1);
}

这里解析腾讯的IP地址
在这里插入图片描述
在这里插入图片描述

getnameinfo()函数用于将IP地址转换为主机名和端口号的可读字符串形式,这个函数支持IPv4和IPv6,这里只做语法介绍。

int getnameinfo(const struct sockaddr *sa, socklen_t salen,char *host, socklen_t hostlen,char *serv, socklen_t servlen, int flags);
//sa: 指向sockaddr结构的指针,包含要解析的地址信息。
//salen: sockaddr结构的大小。
//host: 用于存储解析后的主机名的缓冲区的指针。
//hostlen: host缓冲区的长度。
//serv: 用于存储解析后的端口号的字符串的缓冲区的指针,可以为NULL,如果不需要服务名。
//servlen: serv缓冲区的长度。
//flags: 控制getnameinfo行为的标志位,可以是以下值的组合://0: 默认行为。//NI_NOFQDN: 仅返回主机名而不返回完全限定的域名(FQDN)。//NI_NUMERICHOST: 强制返回数值形式的主机地址,忽略gethostbyaddr的解析。//NI_NAMEREQD: 如果节点名未知,则要求返回错误。//NI_NUMERICSERV: 返回服务的数值形式而不是服务名称。//NI_DGRAM: 服务指定为数据报服务(UDP)。

①Windows系统
gethostbyaddr()getnameinfo()两种函数在Windows系统中的语法,和Linux系统中完全相同,这里就不再赘述,直接给出示例代码:

gethostbyaddr()函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>void error_handling(const char *message); // 错误处理函数声明int main(int argc, char *argv[])
{WSADATA wsaData;int i;struct hostent *host;SOCKADDR_IN addr;// 用于存储IPv4地址信息的结构体if(argc!=2){printf("Usage : %s <addr>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0){printf("WSAStartup() error!\n");exit(1);}memset(&addr, 0, sizeof(addr));addr.sin_addr.s_addr = inet_addr(argv[1]);// 使用gethostbyaddr函数将IP地址转换为hostent结构host=gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr), AF_INET);if(host==NULL){error_handling("gethostbyaddr... error");}// 打印官方主机名printf("Official name: %s \n", host->h_name);for(i=0; host->h_aliases[i]; i++){// 遍历并打印所有别名printf("Aliases %d: %s \n", i+1, host->h_aliases[i]);}// 打印地址类型printf("Address type: %d \n", host->h_addrtype);for(i=0; host->h_addr_list[i]; i++){// 遍历并打印所有IP地址printf("IP addr %d: %s \n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));}// 清理WinsockWSACleanup();return 0;
}// 错误处理函数,打印错误信息并退出程序
void error_handling(const char *message) {fputs(message, stderr);fputc('\n', stderr);exit(1);
}

这里解析腾讯的IP地址
在这里插入图片描述

在这里插入图片描述

相关文章:

  • 项目日记(3) boost搜索引擎
  • LabVIEW如何确保自动化设备的稳定性和可靠性?
  • RocketMQ使用(3):消息重复
  • 其它高阶数据结构⑦_Skiplist跳表_概念+实现+对比
  • 人工智能应用-实验8-用生成对抗网络生成数字图像
  • 计网(部分在session学习章)
  • Unity Physics入门
  • 【竞技宝】英超:足总杯踢完解雇腾帅,曼联管理层心意已决
  • 【设计模式深度剖析】【A】【创建型】【对比】| 工厂模式重点理解产品族的概念
  • memmove使⽤和模拟实现
  • 数据结构和算法基础(二)
  • 基于 Java 的浏览器——JxBrowser使用分享
  • Sass是什么?有哪些优缺点?
  • 【代码随想录算法训练营第37期 第十七天 | LeetCode110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和】
  • python数据类型之列表
  • [iOS]Core Data浅析一 -- 启用Core Data
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 〔开发系列〕一次关于小程序开发的深度总结
  • Android Volley源码解析
  • Docker: 容器互访的三种方式
  • ECMAScript6(0):ES6简明参考手册
  • ES2017异步函数现已正式可用
  • ES6 ...操作符
  • ES6--对象的扩展
  • Hibernate【inverse和cascade属性】知识要点
  • Intervention/image 图片处理扩展包的安装和使用
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • Java小白进阶笔记(3)-初级面向对象
  • MobX
  • mysql中InnoDB引擎中页的概念
  • SpiderData 2019年2月25日 DApp数据排行榜
  • 测试开发系类之接口自动化测试
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • linux 淘宝开源监控工具tsar
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • #mysql 8.0 踩坑日记
  • #QT项目实战(天气预报)
  • (3)(3.5) 遥测无线电区域条例
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (办公)springboot配置aop处理请求.
  • (分布式缓存)Redis哨兵
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (四)图像的%2线性拉伸
  • (一)插入排序
  • (转)3D模板阴影原理
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转)机器学习的数学基础(1)--Dirichlet分布