介绍了当你打开浏览器时,访问网页这个动作涉及到的整个网络通信的大致流程。涉及了从发起 HTTP 请求开始,过程包含浏览器解析 URL、与 DNS 服务器通信等,直到 Web 服务器给予应答在内的多个方面进行讲解。
下图为第一章内容概览
HTTP请求过程
通过浏览器输入URL
URL(Uniform resource locator,统一资源定位符)
浏览器解析URL
浏览器根据protocol://userInfo@host:port/path?#fragment
格式的各个部分进行解析。
当然,服务器通常会设定一些默认的后缀或者是文件,例如当访问www.baidu.com
或www.baidu.com/index
时,有可能读取到的是服务器中/index.html
这个页面。另外的情况是,还可能是服务器配置好的其他映射。
还需要了解的是对于访问www.baidu.com/dir
来说,由于末尾没有标识文件夹的/
符号,但处理惯例是:如果服务器上存在名为 dir 的文件,则将该资源作为文件来处理;否则作为文件夹处理。(注意:在同一目录下,无法创建相同名称的文件和文件夹)
HTTP基本传输过程
一般来说,URI(Uniform Resource Identifier) 的内容是一个静态资源或者是一个CGI程序文件。还有一种可能是 Web 服务器通过重写规则对虚拟的 URI 进行映射达到返回指定资源的目的。
下图是HTTP的方法内容
我们通过 HTTP 方法指定向服务器资源的方式,URI 定位资源的位置最终将请求包装成报文发送给 Web 服务器。而服务器通过对报文的解析,并进行相应的逻辑处理后,将返回结果存放至响应消息中返回给客户端。
发送HTTP请求消息
报文格式
在确定了 URL 后,浏览器根据解析的内容并依据以下格式来生成消息。
需要了解的是,GET 方法发送的数据只有几百字节,超过这一长度则必须使用 POST。
请求发送及报文状态行组装
下图展示了完整的 HTTP 表单提交
报文请求头组装
报文请求体组装
写完消息头之后,还需要添加一个完全没有内容的空行,然后写上需要发送的数据。这一部分称为消息体,也就是消息的主体。不过,在使用GET方法的情况下,仅凭方法和URI,Web服务器就能够判断需要进行怎样的操作,因此消息体中不需要填写任何数据。消息体结束之后,整个消息也就结束了。当使用POST方法时,需要将表单中填写的信息写在消息体中。到此为止,请求消息的生成操作就全部完成了。
接收HTTP响应消息
报文格式
状态码
返回响应消息之后,浏览器会将数据提取出来并显示在屏幕上,到这里就全部处理完毕了。
1 条请求消息中只能写 1 个URI。如果需要获取多个文件,必须对每个文件单独发送 1 条请求。
完整过程
向DNS服务器查询Web服务器的IP地址
在应用委托操作系统发送消息时,必须要提供的不是通信对象的域名,而是它的 IP 地址。因此,在生成 HTTP 消息之后,下一个步骤就是根据域名査询 IP 地址。
发送者发出的消息报文首先经过子网中的集线器,转发到距离发送者最近的路由器上。接下来,路由器会根据消息的目的地判断下一个路由器的位置,然后将消息发送到下一个路由器,即消息再次经过子网内的集线器被转发到下一个路由器。前面的过程不断重复,最终消息就被传送到了目的地。
IP的结构和划分
在 IP 地址的规则中,网络号和主机号连起来总共是 32 比特,但这两部分的具体结构是不固定的。在组建网络时,用户可以自行决定它们之间的分配关系。因此,通过 IP 和子网掩码来划分网络号和主机号。
IP 地址的主机号
全 0 表示为整个子网
全 1 表示向子网上所有设备发送包,即广播
DNS解析器与DNS服务器通信
DNS(Domain Name System,域名服务系统)。将服务器名称和 IP 地址进行关联是 DNS 最常见的用法,但DNS的功能并不仅限于此,它还可以将邮件地址和邮件服务器进行关联,以及为各种信息关联相应的名称。
DNS服务器接力
来自客户端的查询消息包含以下3种信息:
域名
服务器、邮件服务器(邮件地址中@后面的部分)的名称。
class
在最早设计 DNS 方案时,DNS 在互联网以外的其他网络中的应用也被考虑到了,而 Class 就是用来识别网络的信息。不过,如今除了互联网并没有其他的网络了,因此 Class 的值永远是代表互联网的 IN。
记录类型
表示域名对应何种类型的记录。例如,当类型为 A(Address) 时,表示域名对应的是 IP 地址;当类型为 MX(Mail eXchange) 时,表示域名对应的是邮件服务器。对于不同的记录类型,服务器向客户端返回的信息也会不同。
DNS 服务器上事先保存有前面这 3 种信息对应的记录数据,并根据这些记录查找符合查询请求的内容并对客户端作出响应的。
例如:查询条件为www.lab.glasscom.com IN A
,则返回192.0.2.226
。
域名的层次结构
拿www.tarot.com.cn
这个域名举例。可以把域名层次划分想象成一个多叉树,它的根节点在域名划分里叫做根域,用符号.
来表示。而它下面的cn
域则代表分配给中国的域名,而com
代表分配给公司的域名,由右至左级级递减。因此可以从任意一台 DNS 服务器,顺着连接关系找到根域 DNS 服务器,再找到全世界的 DNS 服务器。每一个 DNS 服务器需要注册到它的上级域 DNS 服务器并缓存和管理它的下级域(子域) DNS 服务器。
DNS服务器之间的查询操作
收到客户端的査询消息之后,DNS 服务器会按照前面的方法来査询 IP 地址,并返回给客户端。这样,客户端就知道了 Web 服务器的 IP 地址,也就能够对其进行访问了。以上就是向 DNS 服务器查询 IP 地址的实际过程。
通过缓存加快DNS服务器的响应
上面介绍的是基本原理,与真实互联网中的工作方式还是有一些区别的。在真实的互联网中,一台 DNS 服务器可以管理多个域的信息,因此并不是每个域都有一台自己的 DNS 服务器。现实中上级域和下级域有可能共享同台 DNS 服务器。在这种情况下,访问上级 DNS 服务器时就可以向下跳过一级 DNS 服务器,直接返回再下一级 DNS 服务器的相关信息。
此外,有时候并不需要从最上级的根域开始査找,因为 DNS 服务器有个缓存功能,可以记住之前査询过的域名。如果要查询的域名和相关信息已经在缓存中,那么就可以直接返回响应,接下来的査询可以从缓存的位置开始向下进行。相比每次都从根域找起来说,缓存可以减少査询所需的时间。
并且,当要查询的域名不存在时,“不存在” 这一响应结果也会被缓存。这样,当下次査询这个不存在的域名时,也可以快速响应。
这个缓存机制中有一点需要注意,那就是信息被缓存后,原本的注册信息可能会发生改变,这时缓存中的信息就有可能是不正确的。因此,DNS 服务器中保存的信息都设置有一个有效期,当缓存中的信息超过有效期后,数据就会从缓存中删除。而且,在对査询进行响应时,DNS 服务器也会告知客户端这一响应的结果是来自缓存中还是来自负责管理该域名的 DNS 服务器。
委托协议栈发送消息
主要分为四个阶段:创建Socket阶段、连接阶段、通信阶段、主动断开连接。