一个HTTP请求的曲折经历

原文: https://www.neroht.com/article-detail/18 一个HTTP请求的曲折经历 nero发布于 2020-04-30 09:04:73 写在前面 作为程序员的我们每天都在和网络请求打交道,而前端程序员接触的最多的就是HTTP请求。平时工作中,处理网络请求之类的操作是最多的了。但是一个请求从客户端发出到被服务端处理、再回送响应,再被客户端接收这一个闭环的底层细节可能并没有深究过,本篇文章是我的一篇读书笔记,总结出来恰好涉及到了这一过程,分享出来希望可以对大家有所启发。 文中某些点如果表述有误,欢迎指出来,不胜感激。 从一个经典的面试题说起 从输入URL到页面展现的过程 输入URL后,会先进行域名解析。优先查找本地host文件有无对应的IP地址,没有的话去本地DNS服务器查找,还不行的话,本地DNS服务器会去找根DNS服务器要一个域服务器的地址进行查询,域服务器将要查询的域名的解析服务器地址返回给本地DNS,本地DNS去这里查询就OK了。 浏览器拿到服务器的IP地址后,会向它发送HTTP请求。HTTP请求经由一层层的处理、封装、发出之后,最终经由网络到达服务器,建立TCP/IP连接,服务器接收到请求并开始处理。 服务器构建响应,再经由一层层的处理、封装、发出后,到达客户端,浏览器处理请求。 浏览器开始渲染页面,解析HTML,构建render树,根据render树的节点和CSS的对应关系,进行布局,绘制页面。 这4个步骤包含了一个HTTP请求的完整生命周期,文章着重介绍第2步和第3步,也就是请求是如何在两个物理端点之间进行通信的。数据的发出和接收必然会经历一些处理、解析的过程,这些过程在系统的不同层次进行。 分层 一个HTTP请求从源端发出到在终端接收的处理过程都是要经过以下四层。其中每一层都有各自的协议。 我们先来理解一下协议是什么,协议是经过约定,双方共同承认,并且需要共同遵守的规则。上面的每一层,都有各自的协议,协议的执行者是通信链路两端内的对应层。每一层通过协议来理解数据,并进行处理。 上图中只举例出了最常见的协议,实际上每一层都有细分的协议: 应用层:应用程序负责将数据以相应规则(协议)进行包装,发给传输层 HTTP:超文本传输协议 FTP:文件传输协议 SMTP:简单邮件传送协议 SNMP:简单网络管理协议 传输层:负责将应用层传过来的数据进行分组,为确保终端接收数据的顺序和完整性,会对每个分组进行标记,交给网络层 TCP:传输控制协议 UDP:用户数据协议 网络层:负责将传输层发来的数据分组发送到目标终端 IP:网际协议 ICMP:Internet互联网控制报文协议 IGMP:Internet组管理协议 链路层:为网络层发送和接收数据单元 ARP:地址解析协议 RARP:逆地址解析协议 封装和分用 数据在经过每一层的时候都要被对应的协议包装,到达终端的时候,要一层一层的解包。这两个过程叫封装和分用。 发送时,用户数据被HTTP封装为报文,每一层会将上层传过来的报文作为本层的数据块,并添加自己的首部,其中包含了协议标识,这一整体作为本层报文向下传递。 接收时,数据自下而上流动,经过每一层时被去掉报文首部,根据报文标识确定正确的上层协议,最终到应用层被应用程序处理。 封装 源端发送HTTP报文时,报文会以数据流的形式通过一条已经打开的TCP连接按序传输,TCP收到数据流后会将其分割成小的数据块,每个小块被添加的TCP首部与数据块共同组成了TCP分组,分组经由网络层发送,网络层遵循IP协议,当收到分组发送请求后,会将分组其放入IP数据报,填充报头,将数据报发经由链路层发送出去。 这一过程经过每层的时候都会被增加一些首部信息,有时还需要增加尾部信息,每一层都会把数据封装到各自的报文中, 并在报文首部添加协议标识,这个过程叫封装。 分用 终端接收到一个以太网数据帧时,数据自底层向上流动,去掉发送时各层协议加上的报文首部,每层协议都要检查报文首部的协议标识,从而确定上层协议,保证数据被正确处理,这个过程叫分用。 终端从链路层接收到数据请求后,进入网络层对数据进行解析,交给给传输层,校验分组顺序和完整性,从数据块中取出数据,得到HTTP报文,交给应用层进行处理。这个过程会逐层剥离报头还原数据。 逐层分析 我们已经知道,数据是从源端自上而下到终端自下而上被一层层处理的,现在就来看一下每层都做了什么事情。 HTTP HTTP属于应用层,用户触发交互所产生的行为数据和服务端对此的响应都由它封装成HTTP报文,再交由下层协议进行处理。报文的作用是客户端与服务端沟通的载体,双方都要遵循统一规则对信息进行处理,这一规则称为HTTP。 …

ASCII – 维基百科

https://zh.wikipedia.org/wiki/ASCII ASCII(发音: /ˈæski/ ASS-kee[1],American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语,而其扩展版本延伸美国标准信息交换码则可以部分支持其他西欧语言,并等同于国际标准ISO/IEC 646。1968年版ASCII编码速见表 美国信息交换标准代码是这套编码系统的传统命名,互联网号码分配局现在更倾向于使用它的新名字US-ASCII[2]。 美国信息交换标准代码是美国电气和电子工程师协会里程碑之一。 目录 1概览 2控制字符 3可显示字符 4缺点 5参见 6参考资料 概览 ASCII 由电报码发展而来。第一版标准发布于1963年[3][4],1967年经历了一次主要修订[5][6],最后一次更新则是在1986年,至今为止共定义了128个字符;其中33个字符无法显示(一些终端提供了扩展,使得这些字符可显示为诸如笑脸、扑克牌花式等8-bit符号),且这33个字符多数都已是陈废的控制字符。控制字符的用途主要是用来操控已经处理过的文字。在33个字符之外的是95个可显示的字符。用键盘敲下空白键所产生的空白字符也算1个可显示字符(显示为空白)。 控制字符 说明: Unicode表示法:当我们想在画面或纸张上表示这些控制字符时,就会显示成这个样子。过于老旧的系统或浏览器可能会看不到。使用微软任一中文输入法,输入`U2400即可看到␀,输入`U2401可看到␁,依此类推。 脱出字符表示法:通常用于终端连线(例如Telnet通信协议),以脱出字符^开头,再接一个符号,用来让这些控制字符得以在画面上显现。虽然看起来是两个字符,但在终端上实际只有一个字符。在绝大部分的终端系统中,包括Windows的命令提示字符(cmd.exe)、Linux和FreeBSD,都可用Ctrl代表脱出字符,输入想要的ASCII控制字符。例如想输入空字符,就要输入Ctrl+2,而非^@,后者会显示成两字符,前者只会显示成一字符。 二进制 十进制 十六进制 缩写 Unicode表示法 脱出字符表示法 名称/意义 0000 0000 0 00 NUL ␀ ^@ 空字符(Null) 0000 0001 1 01 SOH ␁ ^A 标题开始 0000 0010 2 02 STX ␂ ^B 本文开始 0000 0011 3 …