域名系统 DNS

DNS 概述

        域名系统 DNS(Domain Name System)是因特网使用的命名系统,用来把便于人们使用的机器名字转换成为 IP 地址。域名系统其实就是名字系统。为什么不叫“名字”而叫“域名”呢?这是因为在这种因特网的命名系统中使用了许多的“域(domain)”,因此就出现了“域名”这个名词。“域名系统”明确地指明这种系统是应用在因特网中。我们都知道,IP 地址是由 32 位的二进制数字组成的。用户与因特网上某台主机通信时,显然不愿意使用很难记忆的长达 32 位的二进制主机地址。即使是点分十进制 IP 地址也并不太容易记忆。相反,大家愿意使用比较容易记忆的主机名字。但是,机器在处理 IP 数据报时,并不是使用域名而是使用 IP 地址。 这是因为 IP 地址长度固定,而域名的长度不固定,机器处理起来比较困难。
        例如,www.baidu.com 就是一个域名,那么域名解析的过程就是:
www.baidu.com-->DNS 服务器(把域名转成 IP)-->转换为 IP(http://14.215.177.39/)

DNS 协议运行在 UDP 协议上面,是一个 UDP 的“回显”程序,使用 53 号端口

因特网的域名结构

从语法上讲,每一个域名都是有标号(label)序列组成,而各标号之间用点(小数点)隔开。如下例子所示:

        上图这是中央电视台用于手法电子邮件的计算机的域名,它由三个标号组成,其中标号com 是顶级域名,标号 cctv 是二级域名,标号 mail 是三级域名。
        DNS 规定,域名中的标号都有英文和数字组成, 每一个标号不超过 63 个字符 ( 为了记忆方 便,一般不会超过 12 个字符 ) ,也不区分大小写字母。
        级别最低的域名写在最左边,而级别最高的字符写在最右边。由多个标号组成的完整域名总共不超过 255 个字符。
        DNS 既不规定一个域名需要包含多少个下级域名,也不规定每一级域名代表什么意思。各级域名由其上一级的域名管理机构管理,而最高的顶级域名则由 ICANN 进行管理。用这种方法可使每一个域名在整个互联网范围内是唯一的,并且也容易设计出一种查找域名的机制。

DNS 协议

首部格式

        DNS 请求与响应的格式是一致的,其头部分为 Header Question Answer Authority
Additional5 部分,如下图所示:

Header 部分是一定有的,长度固定为 12 个字节;其余 4 部分可能有也可能没有,并且长度也不一定,这个在 Header 部分中有指明。 Header 的结构如下:

下面说明一下各个字段的含义 :
1. 标识符:占 16
        ID:占 16 位。该值由发出 DNS 请求的程序生成,DNS 服务器在响应时会使用该 ID,这样便于请求程序区分不同的 DNS 响应。
2. 标志:占 16
        QR:占 1 位。指示该消息是请求还是响应。0 表示请求;1 表示响应。
        OPCODE:占 4 位。指示请求的类型,有请求发起者设定,响应消息中复用该值。0 表示标准查询;1 表示反转查询;2 表示服务器状态查询。3~15 目前保留,以备将来使用。
        AA(Authoritative Answer,权威应答):占 1 位。表示响应的服务器是否是权威DNS 服务器。只在响应消息中有效。
        TC(TrunCation,截断):占 1 位。指示消息是否因为传输大小限制而被截断。
        RD(Recursion Desired,期望递归):占 1 位。该值在请求消息中被设置,响应消息复用该值。如果被设置,表示希望服务器递归查询。但服务器不一定支持递归查询。
        RA(Recursion Available,递归可用性):占 1 位。该值在响应消息中被设置或被清除,以表明服务器是否支持递归查询。
        Z:占 3 位。保留备用。
        RCODE(Response code):占 4 位。该值在响应消息中被设置。取值及含义如下:
                0:No error condition,没有错误条件;
                1:Format error,请求格式有误,服务器无法解析请求;
                2:Server failure,服务器出错。
                3:Name Error,只在权威 DNS 服务器的响应中有意义,表示请求中的域名不存在。
                4:Not Implemented,服务器不支持该请求类型。
                5:Refused,服务器拒绝执行请求操作。
                6~15:保留备用。QDCOUNT:占 16 位(无符号)。指明 Question 部分的包含的实体数量。
        ANCOUNT:占 16 位(无符号)。指明 Answer 部分的包含的 RR(Resource Record)数 量。
        NSCOUNT:占 16 位(无符号)。指明 Authority 部分的包含的 RR(Resource Record)数量。
        ARCOUNT:占 16 位(无符号)。指明 Additional 部分的包含的 RR(Resource Record)数量。

数据区域

查询名:
        查询名部分长度不定,一般为要查询的域名(也会有 IP 的时候,即反向查询)。 此部分由一个或者多个标示符序列组成,每个标示符以首字节数的计数值来说明该标示符长度,每个名字以 0 结束。计数字节数必须是 0~63 之间。该字段无需填充字节。还是借个例子来说明更直观些,查询名为 http://gemini.tuc.noao.edu 的话,查询名字段如下
查询类型:

查询类:
        一般为 IN(枚举值 1) ,即 Internet 数据

DNS 客户端程序实例

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/socket.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>int sock;
struct sockaddr_in sa;/*
generate_question:解析域名数据
*/
void generate_question(char*dns_name,char*buf,int*len)
{char*pos = dns_name;//指向域名当前位置char*ptr = buf;int n = 0;*len = 0;while(1){n = strlen(pos) - (strstr(pos , ".") ? strlen(strstr(pos , ".")) : 0);//在 pos 中查找"."子串//返回"."在 pos 中第一次出现的地址,若没有找到返回 NULLprintf("%d\n", n);*ptr++ = (unsigned char)n;memcpy(ptr,pos,n);printf("%lu\n",strlen(ptr));printf("%s\n", ptr);*len += n + 1;ptr += n;if(!strstr(pos , ".")){*ptr = (unsigned char)0;ptr ++;*len += 1;break;}pos += n + 1;printf("%s\n", pos);}
}/*
send_dns_request:解析域名数据,并发送数据包
*/
void send_dns_request(char * dns_name)
{unsigned char request[256] = {0}; //保存整个请求报文unsigned char *ptr = request;unsigned char question[128];//存储域名解析数据int question_len;//产生请求(把字符串表示的域名转换成 DNS 要求的格式)generate_question(dns_name , question ,&question_len);printf("%s\n", question);printf("%d\n", question_len);*((unsigned short*)ptr) = 1; //会话标识 IDptr += 2;*((unsigned short*)ptr) = htons(0x0100); //flagsptr += 2;*((unsigned short*)ptr) = htons(1); //Quetions 问题数,通常为 1ptr += 2;*((unsigned short*)ptr) = 0;ptr += 2;*((unsigned short*)ptr) = 0;ptr += 2;*((unsigned short*)ptr) = 0;ptr += 2;//把域名(www.baidu.com)装换为相应的问题格式保存在此处,以\0 结尾memcpy(ptr , question , question_len);ptr += question_len;*((unsigned short*)ptr) = htons(1); //获取 IPV4 地址,查询类型ptr += 2;*((unsigned short*)ptr) = htons(1); //指互联网地址,查询类,一般为 1,表明是 Internet 数据int re = sendto(sock, request,question_len+16 ,0, (structsockaddr*)&sa, sizeof(sa));printf("re = %d\n",re);int i;for(i=0;i<re;i++)//以 16 进制格式打印出来{printf("%02X ",(unsigned char)request[i]);} printf("===================\n");
}/*recv_dns_response:获取域名所对应的 IP 地址,并打印
*/
void recv_dns_response()
{struct sockaddr_in src_addr;socklen_t addrlen = sizeof(src_addr);char buf[255] = {0};int r = recvfrom(sock, buf, 255, 0, (struct sockaddr*)&src_addr,&addrlen);printf("r == %d\n", r);if(r > 0)//收到大于 0 的数据{int i;for(i=r-4;i<r;i++)//以 16 进制格式打印出来{if(i != r-1)printf("%d.",(unsigned char)buf[i]);elseprintf("%d\n",(unsigned char)buf[i]);} }
}//例./main www.baidu.com
int main(int argc, char *argv[])
{if(argc != 2){printf("Usage : %s <domain name>\n",argv[0]);return -1;}//step 1: 创建一个套接字sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock == -1){perror("socket error:");return -1;}//step 2: 绑定一个地址(ip+端口号)memset(&sa, 0,sizeof(sa));sa.sin_family = AF_INET;sa.sin_port = htons(53); //按"网络字节序"来保存一个整数sa.sin_addr.s_addr = inet_addr("114.114.114.114");//发送解析请求send_dns_request(argv[1]);//接收分析结果recv_dns_response();close(sock);return 0;
}

可以看到当按正确的报文形式发送给 DNS 服务器后,接收到的报文后面四个字节存储了解析的 IP 地址

域名解析函数(gethostbyname)

【头文件】
#include <netdb.h>
#include <sys/socket.h>
extern int h_errno;
【函数原型】
struct hostent *gethostbyname(const char *name);
【函数功能】
        使用域名或主机名获取地址
【参数含义】
        [name]: 待解析的域名或主机名
【返回值】
        失败返回 NULL 指针
        成功返回的非空指针指向如下的 hostent 结构体指针
struct hostent
{char *h_name; /* 主机正式名称 */char **h_aliases; /* 别名列表。 */int h_addrtype; /* 主机地址类型。*/int h_length; /* 地址的长度。 */char **h_addr_list; /*来自名称服务器的地址列表。 */#ifdef __USE_MISC# define h_addr h_addr_list[0] /* 地址,用于向后兼容。*/#endif
};
【示例】
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
extern int h_errno;int main(int argc, char **argv)
{if (argc != 2) {printf("Use example: %s www.google.com\n", *argv);return -1;}char *name = argv[1];struct hostent *hptr;hptr = gethostbyname(name);if (hptr == NULL) {printf("gethostbyname error for host: %s: %s\n", name, hstrerror(h_errno));return -1;}//输出主机的规范名printf("\tofficial: %s\n", hptr->h_name);//输出主机的别名char **pptr;char str[INET_ADDRSTRLEN];for (pptr=hptr->h_aliases; *pptr!=NULL; pptr++) {printf("\ttalias: %s\n", *pptr);}//输出 ip 地址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, hptr->h_addr, str, sizeof(str)));}break;default:printf("unknown address type\n");break;}return 0;
}

获取本地主机名(gethostname)

【头文件】
#include <unistd.h>
【函数原型】
int gethostname(char *name, size_t len);
【函数功能】
        获取本地主机名
【参数含义】
        [name]: 保存获取的主机名
        [len]: naem 的最大长度
【返回值】
        成功返回 0,失败返回-1
【示例】
char buf[256] = {0};
int t = gethostname(buf,256);
if(t == 0)
{printf("%s\n",buf);
}

设置本地主机名(sethostname)

【头文件】
#include <unistd.h>
【函数原型】
int sethostname(const char *name, size_t len);
【函数功能】
        设置本地主机名
【参数含义】
        [name]: 设置的主机名
        [len]: naem 的最大长度
【返回值】
        成功返回 0,失败返回-1
【示例】
sethostname ( "jiuyue" , 6 );

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/172825.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

use renv with this project create a git repository

目录 1-create a git repository 2-Use renv with this project 今天在使用Rstudio过程中&#xff0c;发现有下面两个新选项&#xff08;1&#xff09;create a git repository (2) Use renv with this project. 选中这两个选项后&#xff0c;创建新项目&#xff0c;在项目目…

Mac电脑窗口管理Magnet中文 for mac

Magnet是一款Mac窗口管理工具&#xff0c;它可以帮助用户轻松管理打开的窗口&#xff0c;提高多任务处理效率。以下是Magnet的一些主要特点和功能&#xff1a; 分屏模式支持&#xff1a;Magnet支持多种分屏模式&#xff0c;包括左/右/顶部/底部 1/2 分屏、左/中/右 1/3 分屏、…

sharepoint2016-2019升级到sharepoint订阅版

一、升级前准备&#xff1a; 要建立新的sharepoint订阅版环境&#xff0c;需求如下&#xff1a; 1.单服务器硬件需求CPU 4核&#xff0c;内存24G以上&#xff0c;硬盘300G&#xff08;根据要迁移的数量来扩容大小等&#xff09;&#xff1b; 2.操作系统需要windows server 20…

RTCM数据解码

RTCM RTCM数据协议介绍 1. 一帧数据组成 2.数据接收 /*&#xff08;1&#xff09; synchronize frame */ if (rtcm.nbyte 0){if (data ! RTCM3PREAMB)//RTCM3PREAMB&#xff1a;同步码return 0;rtcm.buff[rtcm.nbyte] data;return 0;} //&#xff08;2&#xff09;添加一B…

python下拉框选择测试

把下拉选择的值得打印出来&#xff1a; import tkinter as tk def on_select(event): # 当选择下拉框中的一项时&#xff0c;此函数将被调用 selected event.widget.cget("text") # 获取选中的文本 print(f"You selected: {selected}") # 打印选中…

postgresql|数据库|序列Sequence的创建和管理

前言&#xff1a; Sequence也是postgresql数据库里的一种对象&#xff0c;其属性如同索引一样&#xff0c;但通常Sequence是配合主键来工作的&#xff0c;这一点不同于MySQL&#xff0c;MySQL的主键自增仅仅是主键的属性做一个更改&#xff0c;而postgresql的主键自增是需要序…

【纯离线】Ubuntu离线安装ntp时间同步服务

Ubuntu离线安装ntp服务 准备阶段&#xff1a;下载安装包 apt-get download ntp apt-get download ntpdate 一、服务端( 192.166.6.xx) 1、环境准备 先判断是否已安装 systemd-timesyncd systemctl is-active systemd-timesyncd 如果返回结果是 active&#xff0c;则表示…

JVM虚拟机详解

目录 01JVM由哪些部分组成/运行流程 什么是程序计数器 详细介绍堆 介绍方法区&#xff08;Method Area&#xff09; 直接内存 虚拟机栈(Java Virtual machine Stacks) 垃圾回收是否涉及栈内存 栈内存分配越大越好吗 方法内的局部变量是否线程安全 什么情况下会导致栈…

GoLong的学习之路(十四)语法之标准库 time(时间包)的使用

文章目录 time包跨时区时间戳时间间隔时间操作addSubEqualBeforeAfter 定时器时间格式化解析字符串格式的时间 time包 时间和日期是我们编程中经常会用到的&#xff0c;本文主要介绍了 Go 语言内置的 time 包的基本用法。 time 包提供了一些关于时间显示和测量用的函数。time…

OpenText 安全取证软件——降低成本和风险的同时,简化电子取证流程

OpenText 安全取证软件&#xff0c;行业标准的数字调查解决方案&#xff0c;适用于各种规模和各种行业的组织 降低成本和复杂性 • 远程调查比轮流调查过程更有效 对结果持有信心 • 磁盘级可见性可以完成相关端点数据的搜索和收集 谨慎调查 • 完整的网络调查&#xf…

[动态规划] (一) LeetCode 1137.第N个泰波那契数

[动态规划] (一) LeetCode 1137.第N个泰波那契数 文章目录 [动态规划] (一) LeetCode 1137.第N个泰波那契数题目解析解题思路状态表示状态转移方程初始化和填表顺序返回值 代码实现总结空间优化代码实现 总结 1137. 第 N 个泰波那契数 题目解析 解题思路 状态表示 (1) 题目要…

2023.NET技术沙龙知识学习笔记

目录 一.Bootstrap Blazor UI组件库企业级应用介绍1.Blazor是什么2.为什么要用Blazor3.Bootstrap Blazor是什么 二.使用WebAssembly运行、扩展.NET应用程序1.WebAssembly简介2.WebAssembly的起源3.为什么选择二进制格式&#xff1f;4.WebAssembly与传统JavaScript的对比5.执行速…

数据结构之队列(源代码➕图解➕习题)

前言 在学过栈之后&#xff0c;会了解到栈的底层是根据顺序表或者链表来构建的&#xff0c;那么我们今天要学习的队列是否也是基于顺序表和链表呢&#xff1f;那我们直接进入正题吧&#xff01; 1. 队列的概念&#xff08;图解&#xff09; 还是跟上节一样&#xff0c;依旧用图…

Linux中shell脚本练习

目录 1.猜数字 2.批量创建用户 3.监控网卡Receive Transmit 数据的变化 4.部署Linux 5.系统性能检测脚本 6.分区脚本 7.数据库脚本 1.猜数字 随机数的生成 使用环境变量RANDOM&#xff0c;范围是0&#xff5e;32767 编写guest.sh&#xff0c;实现以下功能&#xff1…

Servlet 与Spring对比!

前言&#xff1a; Spring相关的框架知识&#xff0c;算是目前公司在用的前沿知识了&#xff0c;很重要&#xff01;&#xff01; 那么以Spring为基础的框架有几个&#xff1f; 以Spring为基础的框架包括若干模块&#xff0c;其中主要的有Spring Framework、Spring Boot、Spring…

MAC安装stable diffusion

./webui.sh --precision full --no-half-vae --disable-nan-check --api Command: "/Users/xxxx/aigc/stable-diffusion-webui/venv/bin/python3" -m pip install torch2.0.1 torchvision0.15.2 Error code: 2 执行命令&#xff1a; pip install torch2.0.1 torchvi…

Linux之J2EE的项目部署及发布

目录 前言 一、会议OA单体项目windows系统部署 1.检验工作 1. 检验jar项目包是否可以运行 2. 验证数据库脚本是否有误 3. 测试项目功能 2. 部署工作 2.1 传输文件 2.2 解压项目及将项目配置到服务器中 2.3 配置数据库 2.4 在服务器bin文件下点击startup.bat启动项目 …

时序预测 | Python实现ARIMA-LSTM差分自回归移动模型结合长短期记忆神经网络时间序列预测

时序预测 | Python实现ARIMA-LSTM差分自回归移动模型结合长短期记忆神经网络时间序列预测 目录 时序预测 | Python实现ARIMA-LSTM差分自回归移动模型结合长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 时序预测 | Python实现ARIMA-LSTM差…

docker应用部署---nginx部署的配置

1. 搜索nginx镜像 docker search nginx2. 拉取nginx镜像 docker pull nginx3. 创建容器&#xff0c;设置端口映射、目录映射 # 在/root目录下创建nginx目录用于存储nginx数据信息 mkdir ~/nginx cd ~/nginx mkdir conf cd conf# 在~/nginx/conf/下创建nginx.conf文件,粘贴下…

【转信创】银河麒麟:系统安全机制

银河麒麟执行脚本时一直显示权限不足&#xff0c;可能需要修改安全状态。 查看当前kysec的相关安全状态&#xff1a; getstatus 修改当前Kysec的相关安全状态&#xff1a; # 设置Kysec安全状态为软/强制模式&#xff1b; sudo setstatus softmode/normal # 关闭执行控制功能…