TCP/IP 不完全详解
TCP/IP是通信协议的统称。首先,我们先认识一下OSI参考模型
OSI 参考模型
OSI 参考模型中各个分层的作用如下:
概括的说:
应用层
:为应用程序提供服务并规定应用程序中通信的相关细节。包括文件传输、电子邮件、远程登陆等协议表示层
:将应用处理的信息转换为适合网络传输的格式,或将下一层的数据转换为上层能够处理的格式。因此它主要负责数据格式的转换。 具体来说,就是将设备固有的数据格式转换为网络标准传输格式。不同设备对比同一比特流解释的结果可能会不同。因此,使它们保持一致是这一层的主要作用。会话层
:负责建立和断开通信链接,以及数据的分割等数据传输相关的管理。传输层
:起着可靠传输的作用。只在通信双方节点上进行处理,而无需在路由器上处理。网络层
:将数据传输到目标地址。目标地址可以是多个网络通过路由器连接而成的某一个地址。因此这一层主要负责寻址和路由选择。数据链路层
:负责物理层面上互连的、节点之间的通信传输。例如与1个以太网相连的2 个节点之间的通信。 将0、1序列划分为具有意义的数据帧传送给对端(数据帧的生成与接收)。物理层
:负责0、1比特流(0、1序列)与电压的高低、光的闪灭之间的互换。
TCP/IP 基础知识
TCP/IP与OSI参考模型
硬件(物理层)
TCP/IP的最底层是负责数据传输的硬件。这种硬件就相当于以太网或电话线路等物理层的设备。关于它的内容一直无法统一定义。因为只要人们在物理层面上所使用的传输媒介不同(如使用网线或无线),网络的带宽、可靠性、安全性、 延迟等都会有所不同,而在这些方面又没有一个既定的指标。总之,TCP/IP是在网络互连的设备之间能够通信的前提下才被提出的协议。
网络接口层(数据链路层)
利用以太网中的数据链路层进行通信,因此属于接口层。也就是说,把它当做让NIC起作用的“驱动程序”也无妨。驱动程序是在操作系统与硬件之间起桥梁作用的软件。计算机的外围附加设备或扩展卡,不是直接插到电脑上或电脑的扩展槽上就能马上使用的,还需要有相应驱动程序的支持。
互联网层(网络层)
互联网层使用IP协议,它相当于OSI模型中的第3层网络层。IP协议基于IP地址转发分包数据。
TCP/IP分层中的互联网层与传输层的功能通常由操作系统提供。尤其是路由 器,它必须得实现通过互联网层转发分组数据包的功能。
此外,连接互联网的所有主机跟路由器必须都实现IP的功能。其他连接互联网的网络设备(如网桥、中继器或集线器)就没必要一定实现IP或TCP的功能。
IP
- ip是跨越网络传送数据包,使整个互联网都能收到数据的协议。ip协议使数据能够发送到地球的另一端,这期间它使用IP地址作为主机的标识。
- IP还隐含着数据链路层的功能。通过IP,相互通信的主机之间不论经过怎样的底层数据链路都能够实现通信。
- 虽然IP也是分组交换的一种协议,但是它不具有重发机制。即使分组数据包未能到达对端主机也不会重发。因此,属于非可靠性传输协议。
ICMP
- IP数据包在发送途中一旦发生异常导致无法到达对端目标地址时,需要给发送端发送一个发生异常的通知。ICMP就是为这一功能而制定的。它有时也被用来诊断网络的健康状况。
ARP
- 从分组数据包的IP地址中解析出物理地址(MAC地址)的一种协议。
传输层
TCP/IP的传输层有两个具有代表性的协议。该层的功能本身与OSI参考模型 中的传输层类似。
传输层最主要的功能就是能够让应用程序之间实现通信。计算机内部,通常同一时间运行着多个程序。为此,必须分清是哪些程序与哪些程序在进行通信。识别这些应用程序的是端口号。
TCP
- TCP是一种面向有连接的传输层协议。它可以保证两端通信主机之间的通信可达。TCP能够正确处理在传输过程中丢包、传输顺序乱掉等异常情况。此外, TCP还能够有效利用带宽,缓解网络拥堵。
- 然而,为了建立与断开连接,有时它需要至少7次的发包收包,导致网络流量的浪费。此外,为了提高网络的利用率,TCP协议中定义了各种各样复杂的规范,因此不利于视频会议(音频、视频的数据量既定)等场合使用。
UDP
- UDP有别于TCP,它是一种面向无连接的传输层协议。UDP不会关注对端是否真的收到了传送过去的数据,如果需要检査对端是否收到分组数据包,或者对端是否连接到网络,则需要在应用程序中实现。
- UDP常用于分组数据较少或多播、广播通信以及视频通信等多媒体领域。
应用层(会话层以上的分层)
TCP/IP的分层中,将OSI参考模型中的会话层、表示层和应用层的功能都集中到了应用程序中实现。这些功能有时由一个单一的程序实现,有时也可能会由多个程序实现。因此,细看TCP/IP的应用程序功能会发现,它不仅实现OSI模型中应用层的内容,还要实现会话层与表示层的功能。
TCP/IP应用的架构绝大多数属于客户端/服务端模型。提供服务的程序叫服务端,接受服务的程序叫客户端。在这种通信模式中,提供服务的程序会预先被部署到主机上,等待接收任何时刻客户可能发送的请求。
客户端可以随时发送请求给服务端。有时服务端可能会有处理异常、超出负载等情况,这时客户端可以在等待片刻后重发一次请求。
WWW
- WWW可以说是互联网能够如此普及的一个重要原动力。用户在一种叫Web 浏览器的软件上借助鼠标和键盘就可以轻轻松松地在网上自由地冲浪。也就是说轻按一下鼠标架设在远端服务器上的各种信息就会呈现到浏览器上。浏览器中既可以显示文字、图片、动画等信息,还能播放声音以及运行程序。
- 浏览器与服务端之间通信所用的协议是HTTP( HyperText Transfer Protocol)。所传输数据的主要格式是HTML( HyperText Markup Language )。WWW中的HTTP属于OSI应用层的协议,而HTML属于表示层的协议。
- 电子邮件其实就是指在网络上发送信件。有了电子邮件,不管距离多远的人,只要连着互联网就可以相互发送邮件。发送电子邮件时用到的协议叫做SMTP。
文件传输(FTP)
- 文件传输是指将保存在其他计算机硬盘上的文件转移到本地的硬盘上,或将本地硬盘的文件传送到其他机器硬盘上的意思。
- 该过程使用的协议叫做FTP(File Transfer Prototol)。FTP很早就已经投入使用、传输过程中可以选择用二进制方式还是文本方式。
- 在FTP中进行文件传输时会建立两个TCP连接,分别是发出传输请求时所要用到的控制连接与实际传输数据时所要用到的数据连接。
远程登录(TELNET与SSH)
- 远程登录是指登录到远程的计算机上,使那台计算机上的程序得以运行的一种功能。TCP/IP网络中远程登录常用TELNET和SSH两种协议。
网络管理(SNMP)
- 在TCP/IP 中进行网络管理时,采用SNMP( Simple Network Management Protocol)协议。使用SNMP管理的主机、网桥、路由器等称作SNMP代理(Agent),而进行管理的那一段叫做管理器(Manager)。SNMP正是这个Manager与Agent所要用到的协议。
- 在SNMP的代理端,保存着网络接口的信息、通信数据量、异常数据量以及设备温度等信息。这些信息可以通过MIB( Management Information Base)访问。因此,在TCP/IP的网络管理中,SNMP属于应用协议,MIB属于表示层协议。
- 一个网络范围越大,结构越复杂,就越需要对其进行有效的管理。而SNMP可以让管理员及时检査网络拥堵情况,及早发现故障,也可以为以后扩大网络收集必要的信息。
TCP/IP 分层模型与通信示例
数据包首部
每个分层中,都会对所发送的数据附加一个首部,在这个首部中包含了该层必要的信息,如发送的目标地址以及协议相关信息。通常,为协议提供的信息为包首部,所要发送的内容为数据。
网络中传输的数据包由两部分组成:一部分是协议所要用到的首部,另一部分是上层传过来的数据。首部的结构由协议的具体规范详细定义。例如,识别上一层协议的域应该从包的哪一位开始取多少个比特、如何计算校验和并插入包的哪一位等。相互通信的两端计算机如果在识别协议的序号以及校验和的计算方法上不一样,就根本无法实现通信。
因此,在数据包的首部,明确标明了协议应该如何读取数据。反过来说,看到首部,也就能够了解该协议必要的信息以及所要处理内容。因此,看到包首部就如同看到协议的规范。首部就像是协议的脸。
示例:发送数据包
假设甲给乙发送电子邮件,内容为:“早上好”。而从TCP/IP通信上看,是从一台计算机A向另一台计算机B发送电子邮件。我们就通过这个例子来讲解一 下TCP/IP通信的过程。
应用程序处理
启动应用程序新建邮件,将收件人邮箱填好,再由键盘输入邮件内容“早上好”,鼠标点击“发送”按钮就可以开始TCP/IP的通信了。
首先,应用程序中会进行编码处理。(UTF-8等)这些编码相当于OSI的表示层功能。
编码转化后,实际邮件不一定会马上被发送出去,因为有些邮件的软件有一次同时发送多个邮件的功能,也可能会有用户点击“收信”按钮以后才一并接收新邮件的功能。像这种何时建立通信连接何时发送数据的管理功能,从某种宽泛的意义上看属于OSI参考模型中会话层的功能。
应用在发送邮件的那一刻建立TCP连接,从而利用这个TCP连接发送数据。 它的过程首先是将应用的数据发送给下一层的TCP,再做实际的转发处理。
TCP模块的处理
TCP根据应用的指示负责建立连接、发送数据以及断开连接。TCP提供将应用层发来的数据顺利发送至对端的可靠传输。
为了实现TCP的这一功能,需要在应用层数据的前端附加一个TCP首部。TCP首部中包括源端口号和目标端口号(用以识别发送主机跟接收主机上的应用)、序号(用以发送的包中哪部分是数据)以及校验和(用以判断数据是否被损坏)。随后将附加了TCP首部的包再发送给IP。
IP模块的处理
IP将TCP传过来的TCP首部和TCP数据合起来当做自己的数据,并在TCP首部的前端在加上自己的IP首部。因此,IP数据包中IP首部后面紧跟着TCP首部,然后才是应用的数据首部和数据本身。IP首部中包含接收端IP地址以及发送端IP地址。紧随IP首部的还有用来判断其后面数据是TCP还是UDP的信息。
IP包生成后,参考路由控制表决定接受此IP包的路由或主机。随后,IP包将被发送给连接这些路由器或主机网络接口的驱动程序,以实现真正发送数据。
如果尚不知道接收端的MAC地址,可以利用ARP( Address Resolution Protocol)查找。只要知道了对端的MAC地址,就可以将MAC地址和IP地址交给以太网的驱动程序,实现数据传输。
网络接口(以太网驱动)的处理
从IP传过来的IP包,对于以太网驱动来说不过就是数据。给这数据附加上以太网首部并进行发送处理。以太网首部中包含接收端MAC地址、发送端MAC地址以及标志以太网类型的以太网数据的协议。根据上述信息产生的以太网数据包将通过物理层传输给接收端。发送处理中的FCS由硬件计算,添加到包的最后。设置FCS的目的是为了判断数据包是否由于噪声而被破坏。
总结如下图:
经过数据链路的包
包流动时,从前往后依此被附加了以太网包首部、IP包首部、TCP包首部 (或者UDP包首部)以及应用自己的包首部和数据。而包的最后则追加了以太网包尾
每个包首部中至少都会包含两个信息:一个是发送端和接收端地址,另一个是上一层的协议类型。
经过每个协议分层时,都必须有识别包发送端和接收端的信息。以太网会用MAC地址,IP会用IP地址,而TCP/UDP则会用端口号作为识别两端主机的地址。即使是在应用程序中,像电子邮件地址这样的信息也是一种地址标识。这些地址信息都在每个包经由各个分层时,附加到协议对应的包首部里边。如图:
此外,每个分层的包首部中还包含一个识别位,它是用来标识上一层协议的种类信息。例如以太网的包首部中的以太网类型,IP中的协议类型以及TCP/UDP中两个端口的端口号等都起着识别协议类型的作用。就是在应用的首部信息中,有时也会包含一个用来识别其数据类型的标签。
数据包接收处理
接收与发送是逆序的过程:
网络接口 (以太网驱动)的处理
主机收到以太网包以后,首先从以太网的包首部找到MAC地址判断是否为发给自己的包。如果不是发给自己的包则丢弃数据。
而如果接收到了恰好是发给自己的包,就查找以太网包首部中的类型域从而确定以太网协议所传送过来的数据类型。在这个例子中数据类型显然是IP包,因此再将数据传给处理IP的子程序,如果这时不是IP而是其他诸如ARP的协议, 就把数据传给ARP处理。总之,如果以太网包首部的类型域包含了一个无法识别的协议类型,则丢弃数据。
IP模块的处理
IP模块收到IP包首部及后面的数据部分以后,也做类似的处理。如果判断得出包首部中的IP地址与自己的IP地址匹配,则可接收数据并从中查找上一层的协议。如果上一层是TCP就将IP包首部之后的部分传给TCP处理;如果是UDP则将IP包首部后面的部分传给UDP处理。对于有路由器的情况下,接收端地址往往不是自己的地址,此时,需要借助路由控制表,在调査应该送达的主机或路由器以后再转发数据。
TCP模块的处理
在TCP模块中,首先会计算一下校验和判断数据是否被破坏。然后检查是否在按照序号接收数据。最后检查端口号,确定具体的应用程序。
数据接收完毕后,接收端则发送一个“确认回执”给发送端。如果这个回执信息未能达到发送端,那么发送端会认为接收端没有接收到数据而一直反复发送。
数据被完整地接收以后,会传给由端口号识别的应用程序。
应用程序的处理
接收端应用程序会直接接收发送端发送的数据。通过解析数据可以获知邮件的收件人地址是乙的地址。如果主机B上没有乙的邮件信箱,那么主机B返回给发送端一个“无此收件地址”的报错信息。
但在这个例子中,主机B上恰好有乙的收件箱,所以主机B和收件人乙能够收到电子邮件的正文。邮件会被保存到本机的硬盘上。如果保存也能正常进行, 那么接收端会返回一个“处理正常”的回执给发送端。反之,一旦出现磁盘满、邮件未能成功保存等问题,就会发送一个“处理异常”的回执给发送端。
由此,用户乙就可以利用主机B上的邮件客户端,接收并阅读由主机A上的用户甲所发送过来的电子邮件——“早上好”。
数据链路
数据链路,指OSI参考模型中的数据链路层,有时也指以太网、无线局域网等通信手段。
数据链路层的协议定义了通过通信媒介互连的设备之间传输的规范。通信媒介包括双绞线电缆、同轴电缆、光纤、电波以及红外线等介质。此外,各个设备之间有时也会通过交换机、网桥、中继器等中转数据。
数据链路也可以被视为网络传输中的最小单位。其实,仔细观察连通全世界的互联网就可以发现,它也不外乎是由众多这样的数据链路组成的,因此又可以称互联网为“数据链路的集合”。
MAC地址
MAC地址用于识别数据链路中互连的节点。以太网或FDDI中,根据IEEE802.3V的规范使用MAC地址。其他诸如无线LAN(IEEE802.lla/b/g/n等)、蓝牙等设备中也是用相同规格的MAC地址。
MAC地址长48比特。MAC地址中3~24位(比特位)表示厂商识别码,每个NICT商都有特定唯一的识别数字。25-48位是厂商内部为识别每个网卡而用。因此,可以保证全世界不会有相同MAC地址的网卡。
IEEE802.3制定MAC地址规范时没有限定数据链路的类型,即不论哪种数据链路的网络(以太网、FDDI、ATM、无线LAN、蓝牙等),都不会有相同的MAC地址出现。
- 例外情况:人们可以在微机板上自由设置自己的MAC地址。再例如,一 台主机上如果启动多个虚拟机,由于没有硬件的网卡只能由虚拟软件自己设定MAC地址给多个虚拟网卡,这时就很难保证所生成的MAC地址是独一无二的了。但是,无论哪个协议成员通信设备,设计前提都是MAC地址的唯一性。这也可以说是网络世界的基本准则。
共享介质型网络
从通信介质(通信,介质)的使用方法上看,网络可分为共享介质型和非共享介质型。
共享介质型网络指由多个设备共享一个通信介质的一种网络。最早的以太网和FDDI就是介质共享型网络。在这种方式下,设备之间使用同一个载波信道进行发送和接收。为此,基本上采用半双工通信方式,并有必要对介质进行访问控制。
共享介质型网络中有两种介质访问控制方式:一种是争用方式,另一种是令牌传递方式。
争用方式
争用方式(Contention)是指争夺获取数据传输的权力,也叫CSMA(载波监听多路访问)。这种方法通常令网络中的各个站采用先到先得的方式占用信道发送数据,如果多个站同时发送帧,则会产生冲突现象。也因此会导致网络拥堵和性能下降。
另在一部分以太网当中,采用了改良CSMA的另一种方式——CSMA/CD方式。CSMA/CD要求每个站提前检査冲突,一旦发生冲突,则尽早释放信道。其具体工作原理如下:
- 如果载波信道上没有数据流动,则任何站都可以发送数据。
- 检査是否会发生冲突。一旦发生冲突时,放弃发送数据同时立即释放载波信道。
- 放弃发送以后,随机延时一段时间,再重新争用介质,重新发送帧。
令牌传递方式
令牌传递方式是沿着令牌环发送一种叫做“令牌”的特殊报文,是控制传输的一种方式。只有获得令牌的站才能发送数据。这种方式有两个特点:一是不会有冲突,二是每个站都有通过平等循环获得令牌的机会。因此,即使网络拥堵也不会导致性能下降。
当然,这种方式中,一个站在没有收到令牌前不能发送数据帧,因此在网络不太拥堵的情况下数据链路的利用率也就达不到100%。为此,衍生了多种令牌传递的技术。例如,早期令牌释放、令牌追加等方式以及多个令牌同时循环等方式。这些方式的目的都是为了尽可能地提高网络性能。
非共享介质网络
非共享介质网络是指不共享介质,是对介质采取专用的一种传输控制方式。在这种方式下,网络中的每个站直连交换机,由交换机负责转发数据帧。此方式下,发送端与接收端并不共享通信介质,因此很多情况下采用全双工通信方式。
不仅ATM采用这种传输控制方式,最近它也成为了以太网的主流方式。通过以太网交换机构建网络,从而使计算机与交换机端口之间形成一对一的连接,即可实现全双工通信。在这种一对一连接全双工通信的方式下不会发生冲突,因此不需要CSMA/CD的机制就可以实现更高效的通信。
半双工与全双工通信
半双工是指,只发送或只接收的通信方式。它类似于无线电收发器,若两端同时说话,是听不见对方说的话的。而全双工不同,它允许在同一时间既可以发送数据也可以接收数据。类似于电话,接打双方可以同时说话。
根据MAC地址转发
在使用同轴电缆的以太网(10BASE5、10BASE2)等介质共享网络中,同一时间只能有一台主机发送数据。当连网的主机数量增加时,通信性能会明显下降。若将集线器或集中器等设备以星型连接,就出现了一款新的网络设备--交换集线器
,这是一种将非介质共享型网络中所使用的交换机用在以太网中的技术,交换集线器也叫做以太网交换机
。
以太网交换机就是持有多个端口的网桥。它们根据数据链路层中每个帧的目标MAC地址,决定从哪个网络接口发送数据。这时所参考的、用以记录发送接口的表就叫做转发表。
交换机转发方式
交换机转发方式有两种,一种叫存储转发,另一种叫直通转发。
存储转发方式检查以太网数据帧末尾的FCS位后再进行转发。因此,可以避免发送由于冲突而被破坏的帧或噪声导致的错误帧。
直通转发方式中不需要将整个帧全部接收下来以后再进行转发。只需要得知目标地址即可开始转发。因此,它具有延迟较短的优势。但同时也不可避免地有发送错误帧的可能性。
IP协议
IP相当于OSI参考模型的第3层
。
IP (IPv4、IPv6)相当于OSI参考模型中的第3层——网络层。网络层的主要作用是“实现终端节点之间的通信”。这种终端节点之间的通信也叫“点对点(end-to-end)通信”。
网络层的下一层一数据链路层的主要作用是在互连同一种数据链路的节点之间进行包传递。而一旦跨越多种数据链路,就需要借助网络层。网络层可以跨越不同的数据链路,即使是在不同的数据链路上也能实现两端节点之间的数据包传输。
IP的主要作用就是在复杂的网络环境中将数据包发给最终的目标地址。
在互联网世界中,将那些配有IP地址的设备叫做“主机”。可以是超天型计算机,也可以是小型计算机。然而,准确地说,主机的定义应该是指“配置有IP地址,但是不进行路由控制的设备”。既配有IP地址又具有路由控制能力的设备叫做“路由器”,跟主机有所区别。而节点则是主机和路由器的统称。
网络层与数据链路层的关系
数据链路层提供直连两个设备之间的通信功能。与之相比,作为网络层的ip则负责在没有直连的两个网络之间进行通信传输。
IP基础知识
IP大致分为三大作用模块,它们是IP寻址、路由(最终节点为止的转发)以及IP分包与组包。
MAC地址
正是用来标识 同一个链路中不同计算机的一种识别码。IP地址
用于在“连接到网络中的所有主机中识别出进行通信的目标地址”。
路由控制
路由控制(Routing)是指将分组数据发送到最终目标地址的功能。即使网络非常复杂,也可以通过路由控制确定到达目标地址的通路。一旦这个路由控制的运行出现异常,分组数据极有可能“迷失”,无法到达目标地址。因此,一个数据包之所以能够成功地到达最终的目标地址,全靠路由控制。
IP属于面向无连接型
ip面向无连接。即在发包之前,不需要建立与对端目标地址之间的连接。上层如果遇到需要发送给ip的数据,该数据会立即被压缩成ip包发送出去。
在面向有连接的情况下,需要事先建立连接。如果对端主机关机或不存在,也就不可能建立连接。反之,一个没有建立连接的主机也不可能发送数据过来。
而面向无连接的情况则不同。即使对端主机关机或不存在,数据包还是会被发送出去。反之,对于一台主机来说,它会何时从哪里收到数据也是不得而知的。通常应该进行网络监控,让主机只接收发给自己的数据包。若没有做好准备很有可能会错过一些该收的包。因此,在面向无连接的方式下可能会有很多冗余的通信。
ip面向无连接的原因
:一是为了简化,二是为了提速。面向连接比起面向无连接处理相对复杂。甚至管理每个连接本身就是一个相当繁琐的事情。此外,每次通信之前都要事先建立连接,又会降低处理速度。需要有连接时,可以委托上一层提供此项服务。因此,ip为了实现简单化与高速化采用面向无连接的方式。
与此对应的上层(传输层)TCP采用的是面向有链接型
ip的作用在于尽力将数据包发送到目的地,它不做最终收到与否的验证
。ip数据包在发送途中可能会出现丢包、错位、数据量翻倍等问题。而这时就需要tcp提供这种保障,tcp负责保证对端主机确实收到收据。
DNS
DNS是用来维护一个用来表示组织内部主机名和IP地址之间对应关系的数据库。在应用中,当用户输入主机名(域名)时,DNS会自动检索那个注册了主机名和IP地址的数据库,并迅速定位对应的IP地址。而且,如果主机名和IP地址需要进行变更时,也只需要在组织机构内部进行处理即可,而没必要再向其他机构进行申请或报告。
域名和域名服务器需要按照分层进行设置。如果域名服务器宕机,那么针对该域的DNS査询也就无法正常工作。因此,为了提高容灾能力,一般会设 置至少两个以上的域名服务器。一旦第一个域名服务器无法提供查询时,就会自动转到第二个甚至第三个域名服务器上进行,以此可以按照顺序进行灾备处理。
进行DNS査询的主机和软件叫做DNS解析器。用户所使用的工作站或个人电脑都属于解析器。一个解析器至少要注册一个以上域名服务器的IP地址。通常,它至少包括组织内部的域名服务器的IP地址。
DNS查询
dns查询机制:
- 计算机A要访问www.baidu.com。
- 首先向域名服务器中查询对应IP地址。
- DNS服务器如果知道IP就直接返回,不知道就会向根域名服务器请求查询。
- 根域名返回地址。
- DNS服务器向www.baidu.com的域名服务器查询IP地址。
- 将查到的IP地址返回给客户端。
- 计算机A建立起跟www.baidu.com的通信。
TCP与UDP
TCP
是面向连接的、可靠的流协议。流就是指不间断的数据结构。TCP为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。
UDP
是不具有可靠性的数据报协议。细微的处理它会交给上层的应用层去完成。在UDP的情况下,虽然可以确保发送消息的大小,却不能保证消息一定会到达。因此有时应用需要做重发处理。
UDP的特点
UDP
不提供复杂的控制机制,利用IP
提供面向无连接的通信服务。并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况下,UDP也无法进行流量控制等避免网络拥塞的行为。此外,传输途中即使出现丢包,UDP也不负责重发。甚至当出现包的到达顺序乱掉时也没有纠正的功能。如果需要这些细节控制,那么不得不交由釆用UDP的应用程序去处理。由于UDP面向无连接,且本身的处理简单高效,因此经常用于以下几个方面:
- 包总量较少的通信(DNS,SNMP等)
- 视频、音频等多媒体通信
- 限定于LAN等特定网络中的应用通信
- 广播通信
TCP的特点
TCP
与UDP
的区别相当大。它充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在UDP中都没有。此外,TCP作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。TCP通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。
TCP握手挥手示意图:
TCP窗口控制与重发控制
在使用窗口控制中,如果出现段丢失,先考虑确认应答未能返回的情况。在这种情况下,数据已经到达 对端,是不需要再进行重发的。然而,在没有使用窗口控制的时候,没有收到确认应答的数据都会被重发。
其次考虑发送时丢失情况,接收主机如果收到一个自己应该接收的序号以外的数据时,会针对当前为止收到数据返回确认应答。如下图:
当某一报文段丢失后,发送端会一直收到序号为1001的确认应答,这个确认应答好像在提醒发送端“我想接收的是从1001开始的数据”。 因此,在窗口比较大,又出现报文段丢失的情况下,同一个序号的确认应答将会被重复不断地返回。而发送端主机如果连续3次收到同一个确认应答、就会将其所对应的数据进行重发。这种机制比之前提到的超时管理更加高效,因此也被称作高速重发控制
。
流控制
发送端根据自己的实际情况发送数据。但是,接收端可能收到的是一个毫无关系的数据包又可能会在处理其他问题上花费一些时间。因此在为这个数据包做其他处理时会耗费一些时间,甚至在高负荷的情况下无法接收任何数据。如此一来,如果接收端将本应该接收的数据丢弃的话,就又会触发重发机制,从而导致网络流量的无端浪费。
为了防止这种现象的发生,TCP提供一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量。这就是所谓的流控制。它的具体操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不超过这个限度的数据。该大小限度就被称作窗口大小。
TCP首部中,专门有一个字段用来通知窗口大小。接收主机将自己可以接收的缓冲区大小放入这个字段中通知给发送端。这个字段的值越大,说明网络的吞吐量越高。
不过,接收端的这个缓冲区一旦面临数据溢出时,窗口大小的值也会随之被设置为一个更小的值通知给发送端,从而控制数据发送量。也就是说,发送端主机会根据接收端主机的指示,对发送数据的量进行控制。这也就形成了一个完整的TCP流控制
。
拥塞控制
一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。在网络出现拥堵时,如果突然发送一个较大量的数据,极有可能会导致整个网络的瘫痪。
TCP为了防止该问题的出现,在通信一开始时就会通过一个叫做慢启动的算法得出的数值,对发送数据量进行控制。
应用协议
应用层协议的定义
利用网络的应用程序有很多,包括Web浏览器、电子邮件、远程登录、文件 传输、网络管理等。能够让这些应用进行特定通信处理的正是应用协议。
TCP和IP等下层协议是不依赖于上层应用类型、适用性非常广的协议。而应用协议则是为了实现某种应用而设计和创造的协议。
TCP/IP的应用层涵盖了 OSI参考模型中第5、第6、第7层的所有功能,不仅包含了管理通信连接的会话层功能、转换数据格式的表示层功能,还包括与对端主机交互的应用层功能在内的所有功能。
远程登录
实现从自己的本地计算机登录到网络另一端计算功能的应用就叫做远程登录
。通过远程登录到通用计算机或UNIX工作站以后,不仅可以直接使用这些主机上的应用,还可以对这些计算机进行参数设置。远程登录主要使用TELNET和SSH两种协议。
TELNET
TELNET利用TCP的一条连接,通过这一条连接向主机发送文字命令并在主机上执行。本地用户好像直接与远端主机内部的Shell相连着似的,直接在本地进行操作。
TELNET可以分为两类基本服务。一是仿真终端功能,二是协商选项机制。
SSH
SSH是加密的远程登录系统。TELNET中登录时无需输入密码就可以发送,容易造成通信窃听和非法入侵的危险。使用SSH后可以加密通信内容。即使信息被窃听也无法破解所发送的密码、具体命令以及命令返回的结果是什么。
文件传输
FTP是在两个相连的计算机之间进行文件传输时使用的协议。
FTP工作机制
FTP使用两条TCP连接来实现文件传输:一条用来控制,另一条用于数据(文件)的传输。
用于控制的TCP连接主要在FTP的控制部分使用。例如登录用户名和密码的验证、发送文件的名称、发送方式的设置。利用这个连接,可以通过ASCII码字符串发送请求和接收应答。在这个连接上无法发送数据,数据需要一个专门的TCP进行连接。
控制用的连接,在用户要求断开之前会一直保持连接状态。不过,绝大多数FTP服务器都会对长时间没有任何新命令输入的用户的连接强制断开。
通常,用于数据传输的TCP连接是按照与控制用的连接相反的方向建立的。
电子邮件
提供电子邮件服务的协议叫做SMTP ( Simple Mail Transfer Protocol) o SMTP为了实现高效发送邮件内容,在其传输层使用了TCP协议。
WWW
WWW定义了3个重要的概念,它们分别是访问信息的手段与位置(URI, Uniform Resource Identifier)、信息的表现形式(HTML, HyperText Markup Language) 以及信息转发(HTTP, HyperText Transfer Protocol)等操作。
URI
URI是Uniform Resource Identifier的缩写,用于标识资源。URI是一种可以用于WWW之外的高效的识别码,它被用于主页地址、电子邮件、电话号码等各种 组合中。
URL常被人们用来表示互联网中资源(文件)的具体位置。但是URI不局限于标识互联网资源,它可以作为所有资源的识别码。现在,在有效的RFC文档中,已经不再使用URL,转而在使用URI,相比URL狭义的概念,URI则是一个广义的概念。因此,URI可以用于除了WWW之外的其他应用协议中。
URI格式
http: //主机名:端口号/路径?访问内容#部分信息
TLS/SSL与HTTPS
通过TLS/SSL对HTTP通信进行加密叫做HTTPS通信。如图:
结尾一道题
文章到这里,已经写的差不多了。接下来由一道题深入巩固一下知识体系
从输入URL到页面加载的过程?
先梳理主干部分:
- 从浏览器接收url到开启网络请求线程(这一部分可以展开浏览器的机制以及进程与线程之间的关系)
- 开启网络线程到发出一个完整的http请求(这一部分涉及到dns查询,tcp/ip请求,五层因特网协议栈等知识)
- 从服务器接收到请求到对应后台接收到请求(这一部分可能涉及到负载均衡,安全拦截以及后台内部的处理等等)
- 后台和前台的http交互(这一部分包括http头部、响应码、报文结构、cookie等知识,可以提下静态资源的cookie优化,以及编码解码,如gzip压缩等)
- 单独拎出来的缓存问题,http的缓存(这部分包括http缓存头部,etag,catch-control等)
- 浏览器接收到http数据包后的解析流程(解析html-词法分析然后解析成dom树、解析css生成css规则树、合并成render树,然后layout、painting渲染、复合图层的合成、GPU绘制、外链资源的处理、loaded和domcontentloaded等)
- CSS的可视化格式模型(元素的渲染规则,如包含块,控制框,BFC,IFC等概念)
- JS引擎解析过程(JS的解释阶段,预处理阶段,执行阶段生成执行上下文,VO,作用域链、回收机制等等)
其它(可以拓展不同的知识模块,如跨域,web安全,hybrid模式等等内容)
从浏览器接收url到开启网络请求线程
浏览器是多进程的,有一个主控进程,以及每一个tab页面都会新开一个进程。
进程可能包括主控进程,插件进程,GPU,tab页(浏览器内核)等等
- Browser进程:浏览器的主进程(负责协调、主控),只有一个
- 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
- GPU进程:最多一个,用于3D绘制
- 浏览器渲染进程(内核):默认每个Tab页面一个进程,互不影响,控制页面渲染,脚本执行,事件处理等(有时候会优化,如多个空白tab会合并成一个进程)
每一个tab页面可以看作是浏览器内核进程,然后这个进程是多线程的,它有几大类子线程
- GUI线程
- JS引擎线程
- 事件触发线程
- 定时器线程
- 网络请求线程
输入URL后,会进行解析(URL的本质就是统一资源定位符)。URL一般包括几大部分:
protocol
,协议头,譬如有http,ftp等host
,主机域名或IP地址port
,端口号path
,目录路径query
,即查询参数fragment
,即#后的hash值,一般用来定位到某个位置
每次网络请求时都需要开辟单独的线程进行,譬如如果URL解析到http协议,就会新建一个网络线程去处理资源下载
因此浏览器会根据解析出得协议,开辟一个网络线程,前往请求资源(这里,暂时理解为是浏览器内核开辟的,如有错误,后续修复)
开启网络线程到发出一个完整的http请求
这一部分主要内容包括:dns查询
,tcp/ip请求构建
,五层因特网协议栈
等等
DNS解析
如果输入的是域名,需要进行dns解析成IP,大致流程:
- 如果浏览器有缓存,直接使用浏览器缓存,否则使用本机缓存,再没有的话就是用host
- 如果本地没有,就向dns域名服务器查询(当然,中间可能还会经过路由,也有缓存等),查询到对应的IP
域名查询时有可能是经过了CDN调度器的(如果有cdn存储功能的话),而且,需要知道dns解析是很耗时的,因此如果解析域名过多,会让首屏加载变得过慢,可以考虑dns-prefetch优化
TCP/IP请求
tcp将http长报文划分为短报文,通过三次握手与服务端建立连接,进行可靠传输。
然后,待到断开连接时,需要进行四次挥手(因为是全双工的,所以需要四次挥手)
tcp/ip的并发限制
浏览器对同一域名下并发的tcp连接是有限制的(2-10个不等)。而且在http1.0中往往一个资源下载就需要对应一个tcp/ip请求
get和post的区别
get和post虽然本质都是tcp/ip,但两者除了在http层面外,在tcp/ip层面也有区别。
get会产生一个tcp数据包,post两个
- get请求时,浏览器会把headers和data一起发送出去,服务器响应200(返回数据),
- post请求时,浏览器先发送headers,服务器响应100 continue,浏览器再发送data,服务器响应200(返回数据)。
http层面区别:
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求在URL中传送的参数是有长度限制的,而POST没有。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中。
五层因特网协议栈
这里的五层就是:应用层、传输层、网络层、数据链路层、硬件层。对应的OSI模型:
从服务器接收到请求到对应后台接收到请求
负载均衡
用户发起的请求都指向调度服务器(反向代理服务器,譬如安装了nginx控制负载均衡),然后调度服务器根据实际的调度算法,分配不同的请求给对应集群中的服务器执行,然后调度器等待实际服务器的HTTP响应,并将它反馈给用户
http报文结构
- 通用头部
Request Url: 请求的web服务器地址
Request Method: 请求方式
(Get、POST、OPTIONS、PUT、HEAD、DELETE、CONNECT、TRACE)
Status Code: 请求的返回状态码,如200代表成功
Remote Address: 请求的远程服务器地址(会转为IP)
- 状态码
1xx——指示信息,表示请求已接收,继续处理
2xx——成功,表示请求已被成功接收、理解、接受
3xx——重定向,要完成请求必须进行更进一步的操作
4xx——客户端错误,请求有语法错误或请求无法实现
5xx——服务器端错误,服务器未能实现合法的请求
// 常见状态码
200——表明该请求被成功地完成,所请求的资源发送回客户端
304——自从上次请求后,请求的网页未修改过,请客户端使用本地缓存
400——客户端请求有错(譬如可以是安全模块拦截)
401——请求未经授权
403——禁止访问(譬如可以是未登录时禁止)
404——资源未找到
500——服务器内部错误
503——服务不可用
- 请求/响应头部
Accept: 接收类型,表示浏览器支持的MIME类型
(对标服务端返回的Content-Type)
Accept-Encoding:浏览器支持的压缩类型,如gzip等,超出类型不能接收
Content-Type:客户端发送出去实体内容的类型
Cache-Control: 指定请求和响应遵循的缓存机制,如no-cache
If-Modified-Since:对应服务端的Last-Modified,用来匹配看文件是否变动,只能精确到1s之内,http1.0中
Expires:缓存控制,在这个时间内不会请求,直接使用缓存,http1.0,而且是服务端时间
Max-age:代表资源在本地缓存多少秒,有效时间内不会请求,而是使用缓存,http1.1中
If-None-Match:对应服务端的ETag,用来匹配文件内容是否改变(非常精确),http1.1中
Cookie: 有cookie并且同域访问时会自动带上
Connection: 当浏览器与服务器通信时对于长连接如何进行处理,如keep-alive
Host:请求的服务器URL
Origin:最初的请求是从哪里发起的(只会精确到端口),Origin比Referer更尊重隐私
Referer:该页面的来源URL(适用于所有类型的请求,会精确到详细页面地址,csrf拦截常用到这个字段)
User-Agent:用户客户端的一些必要信息,如UA头部等
- 常用的响应头部(部分)
Access-Control-Allow-Headers: 服务器端允许的请求Headers
Access-Control-Allow-Methods: 服务器端允许的请求方法
Access-Control-Allow-Origin: 服务器端允许的请求Origin头部(譬如为*)
Content-Type:服务端返回的实体内容的类型
Date:数据从服务器发送的时间
Cache-Control:告诉浏览器或其他客户,什么环境可以安全的缓存文档
Last-Modified:请求资源的最后修改时间
Expires:应该在什么时候认为文档已经过期,从而不再缓存它
Max-age:客户端的本地资源应该缓存多少秒,开启了Cache-Control后有效
ETag:请求变量的实体标签的当前值
Set-Cookie:设置和页面关联的cookie,服务器通过这个头部把cookie传给客户端
Keep-Alive:如果客户端有keep-alive,服务端也会有响应(如timeout=38)
Server:服务器的一些相关信息
cookie
长连接与短连接
TCP/IP 层面:
- 长连接:一个tcp/ip连接上可以连续发送多个数据包,在tcp连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持(类似于心跳包)
- 短连接:通信双方有数据交互时,就建立一个tcp连接,数据发送完成后,则断开此tcp连接
HTTP层面
- http1.0中,默认使用的是短连接,也就是说,浏览器没进行一次http操作,就建立一次连接,任务结束就中断连接,譬如每一个静态资源请求时都是一个单独的连接
- http1.1起,默认使用长连接,使用长连接会有这一行Connection: keep-alive,在长连接的情况下,当一个网页打开完成后,客户端和服务端之间用于传输http的tcp连接不会关闭,如果客户端再次访问这个服务器的页面,会继续使用这一条已经建立的连接
keep-alive不会永远保持,它有一个持续时间,一般在服务器中配置(如apache),另外长连接需要客户端和服务器都支持时才有效
http 2.0
http2.0与http1.1的显著不同点:
- http1.1中,每请求一个资源,都是需要开启一个tcp/ip连接的,所以对应的结果是,每一个资源对应一个tcp/ip请求,由于tcp/ip本身有并发数限制,所以当资源一多,速度就显著慢下来
- http2.0中,一个tcp/ip请求可以请求多个资源,也就是说,只要一次tcp/ip请求,就可以请求若干个资源,分割成更小的帧请求,速度明显提升。
http2.0特性:
- 多路复用(即一个tcp/ip连接可以请求多个资源)
- 首部压缩(http头部压缩,减少体积)
- 二进制分帧(在应用层跟传送层之间增加了一个二进制分帧层,改进传输性能,实现低延迟和高吞吐量)
- 服务器端推送(服务端可以对客户端的一个请求发出多个响应,可以主动通知客户端)
- 请求优先级(如果流被赋予了优先级,它就会基于这个优先级来处理,由服务器决定需要多少资源来处理该请求。)
https
SSL/TLS握手:
- 浏览器请求建立SSL链接,并向服务端发送一个随机数–Client random和客户端支持的加密方法,比如RSA加密,此时是明文传输。
- 服务端从中选出一组加密算法与Hash算法,回复一个随机数–Server random,并将自己的身份信息以证书的形式发回给浏览器(证书里包含了网站地址,非对称加密的公钥,以及证书颁发机构等信息)
- 浏览器收到服务端的证书后
- 验证证书的合法性(颁发机构是否合法,证书中包含的网址是否和正在访问的一样),如果证书信任,则浏览器会显示一个小锁头,否则会有提示
- 用户接收证书后(不管信不信任),浏览会生产新的随机数–Premaster secret,然后证书中的公钥以及指定的加密方法加密
Premaster secret
,发送给服务器。 - 利用Client random、Server random和Premaster secret通过一定的算法生成HTTP链接数据传输的对称加密key-
session key
- 使用约定好的HASH算法计算握手消息,并使用生成的
session key
对消息进行加密,最后将之前生成的所有信息发送给服务端。 - 服务端收到浏览器的回复
- 利用已知的加解密方式与自己的私钥进行解密,获取
Premaster secret
- 和浏览器相同规则生成
session key
- 使用
session key
解密浏览器发来的握手消息,并验证Hash是否与浏览器发来的一致 - 使用
session key
加密一段握手消息,发送给浏览器 - 浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束。
HTTP缓存
缓存可以简单的划分成两种类型:强缓存(200 from cache)与协商缓存(304)
- 强缓存(200 from cache)时,浏览器如果判断本地缓存未过期,就直接使用,无需发起http请求
- 协商缓存(304)时,浏览器会向服务端发起http请求,然后服务端告诉浏览器文件未改变,让浏览器使用本地缓存
http1.1中的缓存控制:
Cache-Control
:缓存控制头部,有no-cache、max-age等多种取值Max-Age
:服务端配置的,用来控制强缓存,在规定的时间之内,浏览器无需发出请求,直接使用本地缓存,注意,Max-Age是Cache-Control头部的值,不是独立的头部,譬如Cache-Control: max-age=3600,而且它值得是绝对时间,由浏览器自己计算If-None-Match/E-tag
:这两个是成对出现的,属于协商缓存的内容,其中浏览器的头部是If-None-Match,而服务端的是E-tag,同样,发出请求后,如果If-None-Match和E-tag匹配,则代表内容未变,通知浏览器使用本地缓存,和Last-Modified不同,E-tag更精确,它是类似于指纹一样的东西,基于FileEtag INode Mtime Size生成,也就是说,只要文件变,指纹就会变,而且没有1s精确度的限制。
Last-Modified
:
- 表明服务端的文件最后何时改变的
- 它有一个缺陷就是只能精确到1s
- 然后还有一个问题就是有的服务端的文件会周期性的改变,导致缓存失效
E-tag
:
- 是一种指纹机制,代表文件相关指纹
- 只有文件变才会变,也只要文件变就会变,
- 也没有精确时间的限制,只要文件一遍,立马E-tag就不一样了
如果同时带有E-tag和Last-Modified,服务端会优先检查E-tag
如果同时启用了Cache-Control与Expires,Cache-Control优先级高。
解析页面流程
- 解析HTML,构建DOM树
- 解析CSS,生成CSS规则树
- 合并DOM树和CSS规则,生成render树
- 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
- 绘制render树(paint),绘制页面像素信息
- 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上
整个渲染步骤中,HTML解析是第一步。简单的理解,这一步的流程是这样的:浏览器解析HTML,构建DOM树。
过程如下 Bytes → characters → tokens → nodes → DOM
- Conversion转换:浏览器将获得的HTML内容(Bytes)基于他的编码转换为单个字符
- Tokenizing分词:浏览器按照HTML规范标准将这些字符转换为不同的标记token。每个token都有自己独特的含义以及规则集
- Lexing词法分析:分词的结果是得到一堆的token,此时把他们转换为对象,这些对象分别定义他们的属性和规则
- DOM构建:因为HTML标记定义的就是不同标签之间的关系,这个关系就像是一个树形结构一样。例如:body对象的父节点就是HTML对象,然后段略p对象的父节点就是body对象
CSS规则树的生成也是类似。
构建渲染树
当DOM树和CSSOM都有了后,就要开始构建渲染树了。一般来说,渲染树和DOM树相对应的,但不是严格意义上的一一对应。因为有一些不可见的DOM元素不会插入到渲染树中,如head这种不可见的标签或者display: none
等。
渲染
有了render树,接下来就是开始渲染,基本流程如下:
- 计算CSS样式
- 构建渲染树
- 布局,主要定位坐标和大小,是否换行,各种position overflow z-index属性
- 绘制,将图像绘制出来
然后,图中的线与箭头代表通过js动态修改了DOM或CSS,导致了重新布局(Layout)或渲染(Repaint)
Layout和Repaint的区别:
- Layout,也称为Reflow,即回流。一般意味着元素的内容、结构、位置或尺寸发生了变化,需要重新计算样式和渲染树
- Repaint,即重绘。意味着元素发生的改变只是影响了元素的一些外观之类的时候(例如,背景色,边框颜色,文字颜色等),此时只需要应用新样式绘制这个元素就可以了
什么会引起回流?
- 页面渲染初始化
- DOM结构改变,比如删除了某个节点
- render树变化,比如减少了padding
- 窗口resize
- 最复杂的一种:获取某些属性,引发回流。很多浏览器会对回流做优化,会等到数量足够时做一次批处理回流,但是除了render树的直接变化,当获取一些属性时,浏览器为了获得正确的值也会触发回流,这样使得浏览器优化无效,包括
- offset(Top/Left/Width/Height)
- scroll(Top/Left/Width/Height)
- cilent(Top/Left/Width/Height)
- width,height
- 调用了getComputedStyle()或者IE的currentStyle
改变字体大小会引发回流
优化方案
- 减少逐项更改样式,最好一次性更改style,或者将样式定义为class并一次性更新
- 避免循环操作dom,创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document
- 避免多次读取offset等属性。无法避免则将它们缓存到变量
- 将复杂的元素绝对定位或固定定位,使得它脱离文档流,否则回流代价会很高
简单层与复合层
- 可以认为默认只有一个复合图层,所有的DOM节点都是在这个复合图层下的
- 如果开启了硬件加速功能,可以将某个节点变成复合图层
- 复合图层之间的绘制互不干扰,由GPU直接控制
- 而简单图层中,就算是absolute等布局,变化时不影响整体的回流,但是由于在同一个图层中,仍然是会影响绘制的,因此做动画时性能仍然很低。而复合层是独立的,所以一般做动画推荐使用硬件加速
资源外链的下载
当遇到外链时,会单独开启一个下载线程去下载资源(http1.1中是每一个资源的下载都要开启一个http请求,对应一个tcp/ip链接)
CSS资源的处理有几个特点
:
- CSS下载时异步,不会阻塞浏览器构建DOM树
- 但是会阻塞渲染,也就是在构建render时,会等到css下载解析完毕后才进行(这点与浏览器优化有关,防止css规则不断改变,避免了重复的构建)
- 有例外,media query声明的CSS是不会阻塞渲染的
JS脚本资源的处理有几个特点
:
- 阻塞浏览器的解析,也就是说发现一个外链脚本时,需等待脚本下载完成并执行后才会继续解析HTML
- 浏览器的优化,一般现代浏览器有优化,在脚本阻塞时,也会继续下载其它资源(当然有并发上限),但是虽然脚本可以并行下载,解析过程仍然是阻塞的,也就是说必须这个脚本执行完毕后才会接下来的解析,并行下载只是一种优化而已
- defer与async,普通的脚本是会阻塞浏览器解析的,但是可以加上defer或async属性,这样脚本就变成异步了,可以等到解析完毕后再执行
注意,defer和async是有区别的: defer是延迟执行,而async是异步执行。
- async是异步执行,异步下载完毕后就会执行,不确保执行顺序,一定在onload前,但不确定在DOMContentLoaded事件的前或后
- defer是延迟执行,在浏览器看起来的效果像是将脚本放在了body后面一样(虽然按规范应该是在DOMContentLoaded事件前,但实际上不同浏览器的优化效果不一样,也有可能在它后面)
遇到图片等资源时,直接就是异步下载,不会阻塞解析,下载完毕后直接用图片替换原有src的地方
loaded和domcontentloaded
- DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片(譬如如果有async加载的脚本就不一定完成)
- load 事件触发时,页面上所有的DOM,样式表,脚本,图片都已经加载完成了
BFC(Block Formatting Context)
特点:
- 内部box在垂直方向,一个接一个的放置
- box的垂直方向由margin决定,属于同一个BFC的两个box间的margin会重叠
- BFC区域不会与float box重叠(可用于排版)
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此
- 计算BFC的高度时,浮动元素也参与计算(不会浮动坍塌)
如何触发BFC?
- 根元素
- float属性不为none
- position为absolute或fixed
- display为inline-block, flex, inline-flex,table,table-cell,table-caption
- overflow不为visible
致谢
本文参考:[从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系!
](https://zhuanlan.zhihu.com/p/...
《图解TCP/IP》
由于本人技术有限,文内如有错误,敬请与我联系,不胜感激!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。