[HTTP 系列] 第 1 篇 —— 从 TCP/UDP 到 DNS 解析

4,201 阅读22分钟

这里是《写给前端工程师的 HTTP 系列》,记得有位大佬曾经说过:“大厂前端面试对 HTTP 的要求比 CSS 还要高”,由此可见 HTTP 的重要程度不可小视。文章写作计划如下,视情况可能有一定的删减,本篇是该系列的第 1 篇 —— 《从 TCP/UDP 到 DNS 解析》。

更多文章可关注我的 interview 系列

写作计划

  • 从 TCP/UDP 到 DNS 解析

  • HTTP 协议那些事

  • Web 服务器 (nginx/caddy)

  • HTTPS (对称加密/非对称加密/SSL)

  • JWT (我自己博客的后台用到了,所以专门要写一篇文章)

  • SPDY / HTTP/2 / Websockets

  • 网络攻击

  • 跨域

  • 缓存机制

  • 浏览器原理

  • 终章:从输入 url 到页面呈现发生了什么

HTTP 的发展历程

HTTP/0.9 标准于 1990 年问世,因为当时的 HTTP 没有作为正式的标准被确立,该版本含有 HTTP/1.0 之前版本的意味。

HTTP/1.0 标准于 1996 年 5 月作为第一份标准被公布,它被记载于 RFC1945 - Hypertext Transfer Protocol -- HTTP/1.0

HTTP/1.1 标准于 1999 年 6 月被公布,截止到目前它应该是最主流的 HTTP 协议版本,它被记载于 RFC2616 - Hypertext Transfer Protocol -- HTTP/1.1

HTTP/2 标准于 2015 年 5 月被正式发布,它被记载于 RFC7540 - Hypertext Transfer Protocol -- HTTP/2,它的特点是 ① 采用二进制而非明文来打包,② 多路复用,③ 修复队头堵塞,④ 允许设置设定请求优先级,⑤ 服务器推送,⑥ WebSocket 等等。

w3techs 统计,截止到 2019/04/22,HTTP/2 的全球占有率为 36%。我的 个人博客 在上线之初就支持了 HTTP/2。

My Website

TCP/IP 通信传输流

TCP/IP 五层协议

在讲解 TCP/IP 通信传输流之前,首先复习一下 TCP/IP 的五层协议。

应用层:决定向用户提供应用服务时通信的活动。TCP/IP 协议族内预存了各类通用的应用服务。比如:FTP、DNS、HTTP 协议。

传输层:传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。在传输层有两个性质不同的协议,分别是 TCP (Transmission Control Protocol,传输控制协议) 和 UDP (User Data Protocol,用户数据报协议)

网络层:网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。该层规定了通过怎样的路径到达对方计算机,并把数据包传送给对方。与对方计算机通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选项内选择一条传输路线。

数据链路层: 在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路,通过差错控制提供数据帧 (Frame)在信道上无差错的传输,并进行各电路上的动作系列。数据的单位称为帧 (frame)

物理层:物理层建立在物理通信介质的基础上,作为系统和通信介质的接口,用来实现数据链路实体间透明的比特 (bit) 流传输。只有该层为真实物理通信,其它各层为虚拟通信。

TCP/IP 数据传输流程

TCP/IP 传输

客户端在应用层 (HTTP 协议) 发出一个 HTTP 请求。

为了方便传输,在传输层 (TCP 协议) 把从应用层处收到的数据 (HTTP 请求报文) 进行分割,并在各个报文上打上标记序号及端口号后转发给网络层。

在网络层 (IP 协议),增加作为通信目的地的 MAC 地址后转发给数据链路层。这样,发送给服务端的请求就准备齐全了。

当服务端在链路层接收到数据时,按序往上层发送,一直到应用层。当传输到应用层时,才算真正的接收到由客户端发送过来的请求

什么是 MAC 地址?

媒体访问控制地址 (Media Access Control Address),也称为局域网地址 (LAN Address),以太网地址 (Ethernet Address) 或物理地址 (Physical Address),它是一个用来确认网上设备位置的地址。ARP (Address Resolution Protocol) 是一种用来解析地址的协议,它可以根据 IP 地址反查出对应的 MAC 地址。

下图展示了一台电脑内网 IP 和 MAC 地址。在终端 (MAC OS 环境) 输入 ifconfig,找到 en0,便可查找本地以太网的信息。

内网IP / MAC地址

那么什么是 MAC 地址呢?我们知道 IP 地址是可变的,可以通过各种方式分配 IP 地址给一个设备,比如 DHCP, PPP,静态 IP 等。而 MAC 地址一般来讲是不会变的,设备在生产时就被“烙”上了 唯一的标识,这个 唯一的标识 就是 MAC 地址。

逼乎上有个很有趣的例子:你中午在公司点了份外卖,收货地址一定是写公司的地址;晚上回到家,再点外卖时就得把地址写成家 (IP 是动态的)。但无论在哪儿点外卖,订单上的姓名和手机号一定是你自己的 (MAC 地址)。

中午外卖小哥把午餐送到公司门口,但收外卖的人肯定不止你一个 (多台设备在同一个 broadcast 网络里),因此他会通过手机号和姓名来找到你。

UDP 协议

用户数据报协议 (User Datagram Protocol),又称使用者资料包协议,是一个简单的面向数据报的传输协议。在 TCP/IP 模型中,UDP 为网络层以上和应用层以下提供了一个简单的接口。UDP 只提供数据的 不可靠传递,它一旦把应用程序发给网络层的数据发送出去,就不保留数据备份。UDP 在 IP 数据报的头部仅仅加入了复用和数据校验 (字段)。

它的特点如下:

  • UDP 缺乏可靠性。UDP 本身不提供确认序号,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次。

  • UDP 头部开销小,它包含以下几个数据:

    • 两个十六位的端口号,分别是源端口和目的端口。

    • 整个数据报文的长度。

    • 整个数据报文的校验和,用于发现头部信息和数据中的错误

  • UDP 是面向无连接的。UDP 客户端和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。

  • UDP 不仅支持单播,还支持多播和广播。

UDP 头部

基于 UDP 协议的有:

  • 域名系统 (DNS)

  • 简单网络管理协议 (SNMP)

  • 动态主机配置协议 (DHCP)

  • 路由信息协议 (RIP)

  • 自举协议 (BOOTP)

  • 简单文件传输协议 (TFTP)

TCP 协议

TCP (Transmission Control Protocol, 传输控制协议) 是一种面向连接的、可靠的、基于字节流服务的传输层通信协议,由 IETF 的 RFC 793 定义。其中字节流服务 (Byte Stream Service) 是指为了方便传输,将大块数据分割成以报文段 (segment) 为单位的数据包进行管理。

  • TCP 提供一种面向连接的、可靠的字节流服务

  • 在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP

  • TCP 使用校验和,确认和重传机制来保证可靠传输

  • TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复

  • TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制

TCP 报文

TCP 报文

端口号:包括源端口号和目的端口号,用来标识同一台计算机的不同的应用进程。TCP 报头中的源端口号和目的端口号同 IP 数据报中的源 IP 与目的 IP 唯一确定一条 TCP 连接。

  • 源端口号:源端口和 IP 地址的作用是标识报文的返回地址。

  • 目的端口号:目的端口指明接收方计算机上的应用程序接口。

序号:它是当前报文段发送的数据组的第一个字节的序号。在 TCP 传送的流中,每一个字节一个序号。比如一个报文段的序号为 300,此报文段的数据部分共有 100 字节,则下一个报文段的序号为 400。序号 确保了 TCP 传输的有序性。

确认号:即 ACK(acknowledgement),指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当 ACK 标志为 1 时才有效。比如建立连接时,SYN 报文的 ACK 标志位为 0。

首部长度:由于首部可能含有可选项内容,因此 TCP 报头的长度是不确定的,报头不包含任何任选字段则长度为 20 字节,4 位首部长度字段所能表示的最大值为 1111,转化为 10 进制为 15,15*32/8 = 60,故报头最大长度为 60 字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。

保留:为将来定义新的用途保留,现在一般置 0。


控制位 说明
URG 紧急指针标志,为 1 时表示紧急指针有效,为 0 则忽略紧急指针。
ACK (acknowledgement) 确认序号标志,为 1 时表示确认号有效,为 0 表示报文中不含确认信息,忽略确认号字段。
PSH push 标志,为 1 表示是带有 push 标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
RST 重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
SYN (synchronize) 同步序号,用于建立连接过程,在连接请求中,SYN=1 和 ACK=0 表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即 SYN=1 和 ACK=1。
FIN (Finish) finish 标志,用于释放连接,为 1 时表示发送方已经没有数据发送了,即关闭本方数据流。

窗口:滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小是一个 16bit 字段,因此窗口大小最大为 65535。

校验和:奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。

紧急指针:只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。

选项和填充:最常见的可选字段是最长报文大小,又称为 MSS (Maximum Segment Size),每个连接方通常都在通信的第一个报文段 (为建立连接而设置 SYN 标志为 1 的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是 32 位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证 TCP 头是 32 的整数倍。

数据部分:TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

TCP 建立连接 (三次握手)

  • 我可以连你嘛?
  • 可以。
  • 那我连了。

emmmmm,单身久了,看三次握手都那么眉清目秀。

上帝请赐给我一个女孩吧,我会好好爱她的!

所谓三次握手 (three-way handshaking) 是指建立一个 TCP 连接时,需要客户端和服务端共发送三个包。它的目的是连接服务器指定端口,建立 TCP 连接,并同步双方的 序列号确认号,交换 TCP 窗口大小信息。在 socket 编程中,当客户端执行 connect() 函数时,将触发三次握手。

  • 第一次握手

    客户端首先发送一个 SYN 为 1 的包给服务端,指明客户端要连接服务端的哪个接口以及初始序号 x。发送完毕后,客户端进入 SYN_SEND 状态。

  • 第二次握手

    服务端收到后,回传一个带有 SYN/ACK 的确认包以示应答。即 SYN=1,ACK=1。服务端选择自己的 ISN 序列号,放到 seq 中,同时将确认序号 ack 设置为客户端的 ISN+1,即 x+1。发送完毕后,服务端进入 SYN_RCVD (同步收到) 状态。

  • 第三次握手

    客户端收到确认后,再次发送一个带 ACK 标志的数据包。即 ACK=1,ack=y+1,并将自己的序列号 seq=x+1。发送完毕后,客户端和服务器双双进入 ESTABLISHED 状态。至此,三次握手结束。

三次握手

TCP 关闭连接 (四次挥手)

  • 客户端:我要睡了
  • 服务端:嗯,睡吧,晚安
  • 服务端:我也要睡了
  • 客户端:晚安,好梦

TAT,好虐。

上帝请赐给我一个女孩吧,我会好好爱她的!

  • 第一次挥手

    客户端调用 close() 函数,并发送一个 FIN (finish) 标志为 1 的数据包给服务端,来表示本方的数据已经全部发送完毕,此时客户端进入 FIN_WAIT_1 状态。TCP 规定,FIN 报文段即使不携带数据,也要消耗一个序号。

  • 第二次挥手

    服务端收到客户端的释放报文后,发出确认报文,其中 ACK=1, ack=u+1,并且带上自己的序列号 seq=v。表明自己接受到了客户端关闭连接的请求,但还没准备好关闭连接 (半关闭状态),也就是说客户端已经没有数据要发送了,但服务端仍有可能会发送数据。发送完毕后,服务端进入 CLOSE_WAIT 状态。

    当客户端收到该报文后,客户端就进入 FIN-WAIT-2 状态,等待服务器发送连接释放报文。

  • 第三次挥手

    服务器端准备好关闭连接时,会向客户端发送一个连接释放报文,其中 FIN=1,ack=u+1。由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为 seq=w。发送完毕后,服务端便进入 LAST-ACK(最后确认) 状态。

  • 第四次挥手

    客户端收到服务器的连接释放报文后,需要发送一个确认包,其中 ACK=1,ack=w+1,而自己的序列号是 seq=u+1,并进入了 TIME-WAIT (时间等待)状态,等待过程可能出现的要求重传的 ACK 包。

    此时 TCP 连接还没有释放,必须经过 2 * MSL (Maximum Segment Lifetime, 最长报文段寿命) 时间后,当客户端撤销相应的 TCB 后,才会进入 CLOSED 状态。

    而服务器只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB 后,就结束了这次的 TCP 连接。因此,服务器结束 TCP 连接的时间要比客户端早一些。

四次挥手

TCP 和 UDP 的对比


UDP TCP
是否连接 无连接 面向连接
是否可靠 不可靠传输,不使用流量控制和拥塞控制 可靠传输,使用流量控制和拥塞控制
连接对象个数 支持一对一,一对多,多对一和多对多交互通信 只能是一对一通信
传输方式 面向报文 面向字节流
首部开销 首部开销小,仅 8 字节 首部最小 20 字节,最大 60 字节
适用场景 适用于实时应用 (IP 电话、视频会议、直播等) 适用于要求可靠传输的应用,例如文件传输

DNS

DNS 报文格式

请求报文和 DNS 服务器返回的应答报文都是统一的格式:

dns-protocol-format.png

  • 会话标识 (2 字节):它是 DNS 报文的 ID 标识,对于请求报文和其对应的应答报文,这个字段是相同的,通过它可以区分 DNS 应答报文是哪个请求的响应。

  • 标志 (2 字节):它有 8 个部分,如下图所示:

    dns-header-flags.png

    字段 说明
    QR (1bit) 查询/响应标志,0 为查询报文,1 为响应报文
    opcode (4bit) 0 表示标准查询,1 表示反向查询,2 表示服务器状态请求,3-15 是保留值
    AA (1bit) 表示授权回答,该字段在应答的时候才有意义,指出给出应答的服务器是查询域名的授权解析服务器;
    TC (1bit) 表示可截断的,用来指出报文比允许的长度还要长,导致被截断
    RD (1bit) 表示期望递归,该字段被请求设置,应答的时候使用的相同的值返回。如果设置了 RD,就建议域名服务器进行递归解析,递归查询的支持是可选的
    RA (1bit) 表示可用递归,该字段在应答中设置或取消,用来代表服务器是否支持递归查询
    RCODE (4bit) 应答码,0 表示没有差错,3 表示名字差错,2 表示服务器错误
    Z 保留值
  • Questions 查询字段

    • QNAME 无符号 8bit 为单位长度不限表示查询名。

    • QTYPE 无符号 16bit 整数表示查询的协议类型。

    • QCLASS 无符号 16bit 整数表示查询的类。

  • Answer/Authority/Additional

    三者的格式相同,如下所示:

    • NAME 资源记录包含的域名。

    • TYPE 表示 DNS 协议的类型。

    • CLASS 表示 RDATA 的类。

    • TTL 表示资源记录可以缓存的时间。0 代表只能被传输,但是不能被缓存。

    • RDLENGTH 表示 RDATA 的长度。

    • RDATA 不定长字符串来表示记录,格式根 TYPE 和 CLASS 有关。比如,TYPE 是 A,CLASS 是 IN,那么 RDATA 就是一个 4 个字节的 ARPA 网络地址。

DNS 解析记录

折腾过搭建网站的小伙伴们一定对 DNS 解析记录不会陌生,下面通过表格复习一下。

类型 助记词 说明
1 A 由域名获得 IPv4 地址 (常用)
2 NS 查询域名服务器 (常用)
5 CNAME 设置域名别名 (常用)
6 SOA 开始授权
11 WKS 熟知服务
12 PTR 把 IP 地址转换成域名
13 HINFO 主机信息
15 MX 邮件交换 (常用)
28 AAAA 由域名获得 IPv6 地址 (常用)
252 AXFR 传送整个区的请求
255 ANY 对所用记录的请求

域名解析过程

  • 系统会检查浏览器缓存中有没有这个域名对应的解析过的 IP 地址,如果缓存中有,这个解析过程就将结束。浏览器缓存是受这个域名的失效时间和缓存的空间大小控制的。

  • 如果用户的浏览器缓存中没有,浏览器会查找操作系统缓存中即为本地的 Host 文件。

  • 路由器也可能会有缓存。

  • 如果前几步都没有找到,就会到 LDNS (Local DNS) 中查找,LDNS 是你的 ISP 分配给你的 DNS (一般为两个),大部分情况下域名都会在这里得到解析。下图是 cloudflare 提供给我的两个 DNS。

    Cloudflare DNS

  • 如果在 LDNS 没有找到,那就要去 Root Server 域名服务器请求解析了。根域名服务器返回给本地域名服务器一个 查询主域名服务器(gTLD Server)地址。gTLD 是国际顶级域名服务器,如.com,.cn、.org 等,全球只有 13 台左右。

  • 本地域名服务器会向 gTLD Server 地址发送请求,它会返回一个 Name Server 域名服务器的地址,这个 Name Server 通常就是你注册域名的厂家,比如 NameCheap、狗爹、万网等等。

  • Name Server 域名服务器会查询存储域名和 IP 的关系映射表,正常情况下都可以根据域名得到目标 IP 记录,并连同一个 TTL 返回给本地域名服务器。

  • 本地域名服务器根据 TTL 缓存这个 IP,并将解析结果返回给客户端,客户端再根据 TTL 将 IP 信息缓存到本地系统缓存里。至此,域名解析过程结束。

域名解析过程

浅谈 CDN

CDN 全称为内容分发网络 (Content Delivery Network),它能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上,以提高用户访问网站的相应速度。

通俗来讲,原本用户访问的资源是存放在你自己的服务器,而现在访问的资源来自 CDN 缓存服务器。在实际操作中,我们只需要将域名的 DNS 解析指向 CDN 服务商提供的域名服务器即可。

我一直在用 cloudflare 的免费版,很赞。它提供了 HTTP/2,IPV6,brotli (一种压缩算法,比 gzip 压缩率还要高的多)。

典型的 CDN 系统由下面两个部分组成:

  • 分发服务系统

分发服务系统的基元是 Cache 设备,它会同步源站点的内容并负责响应用户的访问请求,把缓存在本地的内容快速的提供给用户。

  • 负载均衡系统

对发起请求的用户进行访问调度,确定提供给用户的最终实际访问地址。该系统分为全局负载均衡 (GSLB) 和本地负载均衡 (SLB)。GBLB 主要根据“就近原则”,通过对每个服务节点进行最优判断,向用户提供最合适的 Cache 设备。SLB 主要负责节点内部的设备负载均衡。

CDN 流程

几道面试题

三次握手和四次挥手详细介绍 (重点)

见上文。

TCP 有哪些手段保证可靠交付

  • 为了方便传输,TCP 协议将大块数据分割成以报文段为单位的数据块进行管理。

  • 当 TCP 发出一个报文段时,它会启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

  • 当收到来自另一端的数据时,它会发送一个确认,但该确认不是立即发送的,之所以推迟,是要对包做完整校验。

  • TCP 通过检验 校验和 的方式来检测数据的准确性,当检测到数据出错后,会丢给客户端一个携带 NCK 标志的包,当客户端收到后会重现发送一遍数据包。

  • TCP 协议给每一个字节设置一个序号,序号确保了 TCP 传输的有序性,当报文段出现失序的问题,TCP 会根据序号重新排序。

  • IP 数据报有可能会发生重复,TCP 接收端会丢弃重复的数据。

  • TCP 提供流量控制。TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据。TCP 使用的流量控制协议是可变大小的滑动窗口协议。

为什么是三次握手,两次不行吗?

为了实现可靠数据传输,TCP 协议的通信双方,都必须维护一个序列号,以标识发送出去的数据包中,哪些是已经被对方收到的。三次握手的过程即是通信双方相互告知序列号起始值,并确认对方已经收到了序列号起始值的必经步骤

如果只是两次握手,至多只有连接发起方的起始序列号能被确认,另一方选择的序列号则得不到确认。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP 还设有一个保活计时器 (keep-alive),如果客户端出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为 2 小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔 75 秒发送一次。若一连发送 10 个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

DNS 解析流程 (重点)

见上文。

最后

下一篇将对 HTTP 协议进行全面剖析,敬请期待。

欢迎关注我的微信公众号:进击的前端

进击的前端

参考

《图解 HTTP》 -- 上野宣

TCP 和 UDP

有了 IP 地址,为什么还要用 MAC 地址?

[面试 ∙ 网络] TCP/IP (四):TCP 与 UDP 协议简介

TCP 报文格式详解

TCP 和 UDP 比较

hit-alibaba TCP

TCP 的三次握手与四次挥手 (详解+动图)

当我们谈网络时,我们谈些什么 (4)-- TCP 和 UDP

DNS 协议详解及报文格式分析

DNS 请求报文详解

深入理解 Http 请求、DNS 劫持与解析。

CDN 与 DNS 知识汇总