Simonzhangs' blog Simonzhangs' blog
首页
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • JS设计模式总结
  • 《Vue》
  • 《React》
  • 《TypeScript 从零实现 axios》
  • TypeScript
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • apple music
  • extension
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Simonzhangs

前端学习探索者
首页
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • JS设计模式总结
  • 《Vue》
  • 《React》
  • 《TypeScript 从零实现 axios》
  • TypeScript
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • apple music
  • extension
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术文档

  • GitHub技巧

  • Nodejs

  • 博客搭建

  • Ajax

  • 计算机网络

    • 一篇文章了解cookie与session、token
    • Web开发常见攻击及应对方法
    • 浏览器渲染过程
    • WebSocket梳理
    • 35.TCP协议与UDP协议
    • HTTP常见状态码
    • DNS为什么使用UDP和TCP协议
      • 为什么选择使用 UDP
      • DNS 协议的发展
      • TCP 协议的引入
      • 总结
      • DNS 查询的类型
      • 扩展:MTU 是什么
        • MTU 使用场景
        • MTU 为什么是 1500
    • HTTP协议相关总结
  • 计算机编译原理

  • 涨知识

  • 技术
  • 计算机网络
simonzhangs
2022-05-01
目录

DNS为什么使用UDP和TCP协议

DNS 解析发生在浏览器地址栏输入 url 解析之后,用于将人可以理解的域名系统翻译成机器可以理解的 IP 地址。随着 DNS 的发展,DNS 除了采用 UDP 传输数据外,还会在必要的情况通过 TCP 协议进行数据传输。

# 为什么选择使用 UDP

早期 DNS 查询的数据包都非常小,DNS 查询请求体和响应分别是 15 和 70 字节;相比于 TCP 通信来说,建立三次握手和四次挥手连接时传输的数据消耗开销太大。此外,在实际过程中,DNS 解析往往不会只和一个服务器进行通信,可能会递归地与多个命名服务器进行通信,这样看来会加倍放大 TCP 协议在额外开销上的劣势。

当 DNS 请求体和响应的大小比较小的时候,通过 TCP 协议进行传输不仅需要传输更多的数据,还会消耗更多的资源,多次通信以及信息传输带来的时间成本在 DNS 查询较小时,TCP 的劣势会很明显,TCP 连接的可靠性在 DNS 场景下没有发挥出很大的作用。

# DNS 协议的发展

现在 IPv4 即将无法分配,IPv6 的引入导致 DNS 查询的数据包变大;同时 DNS 协议中提出的 DNSSEC,新增多种资源记录为 DNS 客户端的 DNS 数据来源进行认证,记录的数据往往较大。这些都使得 DNS 需要处理的数据包越来越大,而我们规定一个 UDP 数据包的大小最多可以达到 64kB,这对于一个常见 DNS 查询来说其实已经非常大了;但是在实际生产中,一旦数据包中的数据超过了传输链路的最大传输单元(MTU,也就是单个数据包大小的上限,一般为 1500 字节),当前数据包就可能被分片传输、丢弃等,会导致使用 UDP 协议的 DNS 不稳定。

# TCP 协议的引入

上面说到的由于 DNS 查询数据量过大而导致的数据传输不稳定,这个问题刚好可以使用 TCP 来解决。我们知道 TCP 协议是面向连接的可靠协议,可以通过序列号、超时重传、阻塞控制、滑动窗口、流量控制等机制来保证消息的不重复不遗漏。接收方的 TCP 协议会对分片的数据重新进行拼装,然后上层的 DNS 等应用层协议可以直接使用处理好的完整数据。

同时,当数据包足够大的时候,TCP 三次握手带来的额外开销比例就会越来越小,与整个数据包相比就会趋向于 0 了。所以在 DNS 存储内容较多的时候,TCP 三次握手以及协议头带来的额外开销就不是关键影响因素了,但是 TCP 三次网络传输耗时还是没有办法避免的。

# 总结

DNS 查询在刚设计时主要使用 UDP 协议进行通信,而在 DNS 的演进和发展中 TCP 协议也被加入到规范中。

  1. DNS 设计之初就在区域传输中引入了 TCP 协议,在查询中使用 UDP 协议;
  2. 当 DNS 超过了 512 字节的限制,DNS 协议中规范第一次明确了:当 DNS 查询被截断时,应该使用 TCP 协议进行重试;
  3. 随后引入的 EDNS 机制允许 UDP 最多传输 4096 字节的数据,但是 MTU 的限制导致的数据分片以及丢失,使得 DNS 查询不可靠;
  4. 最近几年,重新规定了 DNS 应该同时支持 UDP 和 TCP 协议,TCP 协议也不再只是重试时的选择了。

# DNS 查询的类型

A 记录、CNAME 记录是常见的查询类型,还包括 AXFR 类型的特殊查询。

# 扩展:MTU 是什么

MTU(Maximum Transmission Unit)最大传输单元,属于数据链路层的概念。MTU 限制的是数据链路层的 payload,也就是上层协议的大小,比如说 IP、ICMP 等。当传输的数据帧大于 MTU 时,上层协议会选择对数据帧进行分片或者直接丢弃。

# MTU 使用场景

当在用笔记本上网时,靠的是路由器通信,路由器连接电信网络,然后访问songbenblog.com,从笔记本出发的一个以太网数据帧总共进过了以下路径:

笔记本 -> 路由器 -> 电信机房 -> 服务器
1

其中,每个节点都有一个 MTU 值,如下:

1500 1500 1500 笔记本 -> 路由器 -> 电信机房 -> 服务器
1

假设我把笔记本的 MTU 最大值设置为 1700,发送时候发了一个超大的 IP 数据包(2000),在外网传输的时候会被拆分成 2 个包,一个 1700、一个 300,然后加上头信息进行传输。

1700 1500 1500 笔记本 -> 路由器 -> 电信机房 -> 服务器
1

当路由器接收了一个数据帧,发现如果大于 MTU 值,在 IP 包 DF 标志位为 1 情况下,路由器会直接将包丢弃;其实本质上 MTU 是在每个节点的管控值,当数据帧大于 MTU 时,要么选择分片要么直接丢弃。

# MTU 为什么是 1500

一个标准的以太网数据帧大小是:1518,头信息有 14 字节(接收方 MAC 地址 48 位、发送方 MAC 地址 48 位、协议类型 16 位 IP),尾部校验和 FCS 占 4 字节,真正留给上层协议传输的数据大小就是 1518-14-4=1500

MTU 值更大不行吗?因为数据链路层的以太网帧是传输中最小可识别单元,再下一层就是物理层 01 数据传送了,一条带宽只能同时发送一个以太网帧,帧太大的话,只能等一帧发送完毕之后再发送下一帧,延迟太大了。

MTU 值更小不行吗?因为以太网帧头尾大小时固定,都是 14+4,所以值设置太小的话,传输效率就降低了。

总之,1518 这个值是考虑到传输效率与传输时间而折中选择的一个值;此外网络链路中的节点太多,其中某个节点的 MTU 值如果和别的节点不一样,很容易带来拆包重组的问题,甚至会导致无法发送。

参考链接:为什么 DNS 使用 UDP 协议 (opens new window) 什么是MTU?为什么MTU值普遍都是1500? (opens new window)

编辑 (opens new window)
上次更新: 2022/05/04, 21:37:45
HTTP常见状态码
HTTP协议相关总结

← HTTP常见状态码 HTTP协议相关总结→

最近更新
01
一些有意思的类比
06-16
02
the-super-tiny-compiler解析
06-06
03
计算机编译原理总概
06-06
更多文章>
Theme by Vdoing | Copyright © 2021-2022
蜀ICP备2021023197号-2
Simonzhans | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 飙升榜
  • 新歌榜
  • 云音乐民谣榜
  • 美国Billboard榜
  • UK排行榜周榜