什么是URL
URL
是统一资源定位符(Uniform Resource Locator),是资源标识最常见的形式。URL
描述了一台特定服务器上某资源的特定位置。它们可以明确说明如何从一个精确、固定的位置获取资源。
URL
说明了协议、服务器和本地资源。
而浏览器都是基于HTTP
协议,而HTTP
是个应用层的协议。HTTP
无需操心网络通信的具体细节都交给了TCP/IP
。
TCP
:
- 无差错的数据传输。
- 按序传输(数据总是按照发送的顺序到达)。
- 未分段的数据流(可以在任意时刻将数据发送出去)。
HTTP协议位于TCP的上层。HTTP使用TCP来传输其报文数据。
解析URL
当用户输入一个完整的URL
之后,浏览器就开始解析URL
的构成,以便于查找资源地址,大多数URL的语法通用格式如下:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
基本上没有哪个URL
包含了所有这些组件。URL
最重要的3个部分是方案scheme
,主机host
和路径path
。
如果URL
中不包含port
,浏览器会默认使用80
端口进行访问。
DNS域名解析
什么是DNS?
DNS
( Domain Name System)是“域名系统”的英文缩写,DNS是应用层协议,事实上他是为其他应用层协议工作的,包括不限于HTTP和SMTP以及FTP,用于将用户提供的主机名解析为ip地址。
DNS 查询的过程如下图所示。
-
在浏览器中输入
www.qq.com
域名,操作系统会先检查自己本地的hosts
文件是否有这个网址映射关系,如果有,就先调用这个IP
地址映射,完成域名解析。 -
如果
hosts
里没有这个域名的映射,则查找本地DNS
解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。 -
如果
hosts
与本地DNS
解析器缓存都没有相应的网址映射关系,首先会找TCP/ip
参数中设置的首选DNS
服务器,在此我们叫它本地DNS
服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。 -
如果要查询的域名,不由本地
DNS
服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP
地址映射,完成域名解析,此解析不具有权威性。 -
如果本地
DNS
服务器本地区域文件与缓存解析都失效,则根据本地DNS
服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS
就把请求发至13台根DNS
,根DNS
服务器收到请求后会判断这个域名(.com
)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP
。本地DNS
服务器收到IP
信息后,将会联系负责.com
域的这台服务器。这台负责.com
域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com
域的下一级DNS
服务器地址(http://qq.com
)给本地DNS
服务器。当本地DNS
服务器收到这个地址后,就会找http://qq.com
域服务器,重复上面的动作,进行查询,直至找到www.qq.com
主机。 -
如果用的是转发模式,此
DNS
服务器就会把请求转发至上一级DNS
服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS
或把转请求转至上上级,以此循环。不管是本地DNS
服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS
服务器,由此DNS
服务器再返回给客户机。
从客户端到本地DNS
服务器是属于递归查询,而DNS服务器之间就是的交互查询就是迭代查询。
建立TCP连接
TCP
根据不同的当前状态(常规或加星)所发送的内容:
常规状态 | 说 明 | 发 送 | 加 星 状 态 | 发 送 |
---|---|---|---|---|
CLOSED | 关闭 | RST, ACK | ||
LISTEN | 监听连接请求(被动打开) | |||
SYN_SENT | 已发出SYN (主动打开) | SYN | SYN_SENT* | SYN, FIN |
SYN_RCVD | 已经发出和收到SYN;等待ACK | SYN, ACK | SYN_RCVD* | SYN, FIN, ACK |
ESTABLISHED | 连接已经建立(数据传输) | ACK | ESTABLISHED* | SYN, ACK |
CLOSE_WAIT | 收到FIN,等待应用程序关闭 | ACK | CLOSE_WAIT* | SYN, FIN |
FIN_WAIT_1 | 已经关闭,发出FIN;等待ACK和FIN | FIN, ACK | FIN_WAIT_1 | SYN, FIN, ACK |
CLOSING | 两端同时关闭;等待ACK | FIN, ACK | CLOSING* | SYN, FIN, ACK |
LAST_ACK | 收到FIN已经关闭;等待ACK | FIN, ACK | LAST_ACK* | SYN, FIN, ACK |
FIN_WAIT_2 | 已经关闭;等待FIN | ACK | ||
TIME_WAIT | 主动关闭后长达2 M S L的等待状态 | ACK |
TCP
中定义了7个扩展状态,这些扩展状态都称为加星状态。它们分别是:SYN_SENT*
、
SYN_RCVD*
、ESTABLISHED *
、CLOSE_WAIT *
、LAST_ACK *
、FIN_WAIT_1 *
和CLOSING *
。
TCP
输入的处理顺序
TCP
协议收到报文段时,对其中所携带的各种控制信息 ( SYN
、FIN
、ACK
、URG
和RST
标志,还可能有数据和选项 )的处理顺序不是随意的,也不是各种实现可以自行决定的。
从 CLOSED
状态到SYN_SENT
状态的变迁就标明发送了一个SYN
报文段。在图中则没有采用这种标记方法,而是在每个状态框中标出处于该状态时要发送的报文段类型。例如,当处于SYN_RECV
状态时,要发出一个带有 SYN
的报文段,其中还包括对所收到SYN
的确认( ACK
)。而当处于CLOSE_WAIT
状态时,要发出
对所收到FIN
的确认( ACK
)。
我们之所以要这样做是因为,在TCP
协议中我们经常需要处理可能造成多次状态变迁的
报文段。于是在处理一个报文段时,重要的是处理完报文段后连接所处的最终状态,因为它决定了应答的内容。而如果不使用TCP
协议,每收到一个报文段通常至多只引起一次状态
变迁,只有在收到SYN/ACK
报文段时才是例外。
三次握手
客户端和服务器之间建立连接需要经过三次确认的阶段,我们称之为TCP
的三次握手。
第一次
客户端发送一个
syn
报文,设置发送序号为X
,客户端进入SYN_SENT
状态,等待服务器回应。
第二次
服务端收到
syn
报文,但是服务端必须确定客户端的syn(ack= X + 1)
, 因此服务端也要发送一个syn=Y
给客户端进行确认,表示服务端已经收到客户端的请求。
服务端需要发送ack+syn
给客户端,此时服务器进入SYN_RECV
状态。
第三次
客户端收到服务器的syn+ack
包,向服务器发送确认包ack(ack=Y+1)
,此包发送完毕,客户端和服务器进入ESTABLISHED
(TCP
连接成功)状态,完成三次握手。
举个例子
比如你走在路上,发现前面有你的朋友向你走过来,你向你朋友挥手(第一次握手)。
你朋友看见了你向他打招呼,但是你朋友因为距离你太远,并不确定是否是跟他打招呼的,因此,你朋友用手指了下自己,并向你示意(第二次握手)。
你看见了你朋友的表情和动作,你需要给你朋友一个肯定,此时,你点头示意(第三次握手)。
此时你和你朋友互相聊天(TCP已连接
)。
四次挥手
由于TCP
连接是全双工的,因此每个方向都必须单独进行关闭。
这原则是当一方完成它的数据发送任务后就能发送一个FIN
来终止这个方向的连接。收到一个 FIN
只意味着这一方向上没有数据流动,一个TCP
连接在收到一个FIN
后仍能发送数据。
首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
TCP
客户端发送一个FIN
,用来关闭客户到服务器的数据传送。- 服务器收到这个
FIN
,它发回一个ACK
,确认序号为收到的序号加1。和SYN
一样,一个FIN
将占用一个序号。 - 服务器关闭客户端的连接,发送一个
FIN
给客户端。 - 客户端发回
ACK
报文确认,并将确认序号设置为收到序号加1。
挥手例子
你和你朋友聊天,聊着聊着,突然想起来女朋友钥匙丢了,你是回家开门的,现在耽误了半小时了,吓得冷汗都出来了,一想起榴莲。。。
这个时候,你赶紧跟你朋友说了情况,你说你马上得回去了,下次再聊(第一次挥手)。
你朋友听了,觉得也是得赶紧回去,就跟你说你赶紧回去吧。(第二次挥手)。
然后,你朋友走了,并向你挥手道别(第三次挥手)。
你看见你朋友跟你道别,你同样也跟你朋友道别(第四次挥手)。
回去之后,你就需要玩玩你的榴莲了。
页面渲染
查看下篇文章 浏览器渲染原理(性能优化之如何减少重排和重绘)
最后
参考文章:
1、HTTP
权威指南。
3、TCP-IP
详解卷