- 要讨论的问题:
- 浏览器如何解析网址?
- 浏览器通过请求消息将用户需要哪些数据告知服务器,请求消息的实际样子?
- 浏览器需要向DNS服务器查询域名对应的IP地址,这一操作如何进行?
- 全世界由上万台DNS服务器,他们相互接力才能完成IP地址的查询,如何接力?
- 查询到IP地址后,浏览器就可以将消息委托给操作系统发送给web服务器了,委托如何完成?
1.1 生成HTTP请求消息
1.1.1 探索之旅从输入网址开始
- http/ ftp/ file/ mailto
- 浏览器不只有访问web服务器这一个功能,也可以用来在FTP服务器上下载和上传文件,同时也具备电子邮件客户端的功能
- 浏览器是一个具备多种客户端功能的综合性客户端软件
- 需要一些东西来判断应该使用其中哪种功能来访问相应的数据
1.1.2 浏览器先要解析URL
- 第一步工作就是对URL进行解析,从而生成发送给Web服务器的请求消息
1.1.3 省略文件名的情况
-
http://www.lab.glasscom.com/dir/
- 以/结尾代表/dir/后面本应该有的文件名被省略了 根据URL的规则,文件名可以被省略,会在服务器上事先设置好文件名省略时要访问的默认文件名
-
http://www.lab.glassroom.com
- 当没有路径名时,就代表访问根目录下事先设置的默认文件
-
http://www.lab.glasscom.com/whatisthis
- 一般来说,这种情况会按照如下惯例处理:
- 如果web服务器上存在名为whatisthis的文件,则将whatisthis作为文件名来处理;
- 如果存在名为whatisthis的目录,则将whatisthis作为目录名来处理
- 一般来说,这种情况会按照如下惯例处理:
1.1.4 HTTP的基本思路
-
首先,客户端会向服务器发送请求消息
-
包含“对什么” + ”进行怎样的操作“两部分
-
”对什么“: URI 统一资源标识符
- 存放网页数据的文件名或者是一个CGI程序的文件名
- CGI程序:对Web服务器调用其他程序的规则所做的定义就是CGI,按照CGI规范来工作的程序就成为CGI程序
- 可以写各种访问目标
- 存放网页数据的文件名或者是一个CGI程序的文件名
-
”进行怎样的操作“:方法(HTTP谓词、动词)
- 需要让Web服务器完成怎样的工作
- 读取URI表示的数据、将客户端输入的数据发送给URI表示的程序等
-
-
收到请求消息之后,Web服务器会对其中的内容进行解析,根据要求完成自己的工作,将结果存放到响应消息中
- 响应消息:
- 开头是状态码:表示操作的执行结果是成功还是发生了错误
- 响应消息:
-
如果只有GET、POST方法,就只能从Web服务器中获取网页数据,以及将网页输入框中的信息发送给Web服务器,而有了PUT和DELETE方法,就能够从客户端修改或者删除Web服务器上的文件了
1.1.5 生成HTTP请求消息
- 浏览器会按照规定的格式来生成请求消息
-
第一行称为请求行
- 开头是方法
- 在地址栏输入网址并显示网页:GET方法
- 点击超级链接的场景:GET方法
- 表单,在HTML源代码中会在表单的属性中指定用哪种方法来发送请求,可能是GET也可能是POST
- GET方法能够发送的数据只有几百个字节,如果表单中数据超过这一长度,必须使用POST方法来发送
- 加一个空格,然后写URI
- 末尾需要写上HTTP的版本号 表示该信息是基于哪个版本的HTTP规格编写的
- 开头是方法
-
第二行开始为消息头
- 定义很多项目,例如日期、客户端支持的数据类型、语言、压缩格式、客户端和服务器的软件名称和版本、数据有效期和最后更新时间等
-
添加一个完全没有内容的空行
-
需要发送的数据(消息体) 消息的主体
- 在使用GET方法时,仅凭方法和URI,Web服务器就知道需要进行怎样的操作,因此消息体中不用填写任何数据
- 当使用POST方法时,需要将表单中填写的信息写在消息体中
-
1.1.6 发送请求后会受到响应
-
响应消息的格式以及基本思路和请求消息是相同的
-
响应消息第一行:
- 状态码 + 响应短语,表示请求的执行结果是成功还是出错
- 状态码是一个数字,用来向程序告知执行的结果
- 响应短语则是一段文字,向人们告知执行的结果
-
返回响应消息之后,浏览器会将数据提取出来并显示在屏幕上
- 如果网页内容只有文字,到这里就处理完毕了
- 当网页中还包括图片等资源,还需要进行另外的处理
- 当网页中包含有图片时,会在网页中的相应位置嵌入表示图片文件的标签的控制信息
- 浏览器会在屏幕上留出用来显示图片的空间
- 再次访问Web服务器,按照标签中指定的文件名向Web服务器请求获取相应的图片并显示在预留的空间中
- 1条请求消息中只能写一个URL,如果要获取多个文件,必须对每个文件单独发送一条请求
- 判断所需的文件,然后获取这些文件并显示在屏幕上,这一系列工作的整体指挥也是浏览器的任务之一,而Web服务器却毫不知情
1.2 向DNS服务器查询Web服务器的IP地址
1.2.1 IP地址的基本知识
- 生成HTTP消息后,需要委托操作系统将消息发送给Web服务器
- 查询网址中服务器域名对应的IP地址 根据域名查询IP地址
- 数据是以包的形式传送的
- IP地址的主机号:
- 全0:表示整个子网
- 全1:表示向子网上所有设备发送包,即“广播”
1.2.2 域名和IP地址并用的理由
- IP地址难记
- 如果不用IP地址而改用域名,使用IP地址只需要处理4字节的数字,而域名则需要处理几十个到255个字节的字符,增加了路由器的负担,传送数据也会花费更长的时间
- 需要有一个机制来通过名称查询IP地址,或者通过IP地址来查询名称 => DNS
1.2.3 Socket库提供查询IP地址的功能
-
DNS解析器:相当于我们电脑上的DNS客户端
-
域名解析:通过DNS查询IP地址
-
将服务器名称和IP地址进行关联是DNS最常见的用法,但DNS的功能并不仅限于此,它还可以将邮件地址和邮件服务器进行关联,以及为各种信息关联相应的名称
-
Socket库是用于调用网络功能的程序组件集合
1.2.4 通过解析器向DNS服务器发出查询
- 根据域名查询IP地址时,浏览器会使用Socket库中的解析器
1.2.5 解析器的内部原理
- HTTP消息使用文本编写的,但DNS消息是使用二进制数据编写的
- 向DNS服务器发送信息时,当然也需要直到DNS服务器的IP地址,这个IP地址是作为TCP/IP的一个设置项目实现设置好的,不用再去查询了
- 协议栈:操作系统内部的网络控制软件,也叫协议驱动,TCP/IP驱动等
1.3 全世界DNS服务器的大接力
1.3.1 DNS服务器的基本工作
-
来自客户端的查询消息包含以下3种消息:
- 域名:服务器、邮件服务器的名称
- Class:最早设计DNS方案时,DNS在互联网以外的其他网络中的应用也被考虑到了,Class是用来识别网络的信息,值永远是代表互联网的IN
- 记录类型:表示域名对应何种类型的记录
- A:IP地址
- MX:邮件服务器
- 当一个邮件地址对应多个邮件服务器时,需要根据优先级来判断哪个邮件服务器是优先的。优先级数值较小的邮件服务器代表更优先
- PTR:根据IP地址反查域名
- CNAME:查询域名相关别名
- NS:查询DNS服务器IP地址
- SOA:查询域名属性信息
-
Web服务器的域名很多都是以www开头的,但这并不是一定的
- 无论是WebServer1也好,MySrc也好,只要是作为A记录在DNS服务器上注册的,都可以作为Web服务器的域名
-
DNS服务器会从域名与IP地址的对照表中查找相应记录,并返回IP地址
1.3.2 域名的层次结构
- DNS服务器中的所有信息都是按照域名以分层次的结构来保存的
- DNS中的域名都是用句点来分隔的 句点代表了不同层次之间的界限
- 在域中,越靠右的位置表示其层级越高
- 一个域的信息是作为一个整体存放在DNS服务器中的,不能将一个域拆开来存放在多台DNS服务器中
- 但DNS服务器与域之间也并不总是一对一的,一台DNS服务器中也可以存放多个域的信息
- 下级的域称为“子域”
1.3.3 寻找相应的DNS服务器并获取IP地址
-
将负责管理下级域的DNS服务器的IP注册到它们的上级DNS服务器中,然后上级DNS服务器的IP地址再注册到更上一级的DNS服务器中,以此类推
-
这样一来可以通过上级DNS服务器查询出下级DNS服务器的IP地址,也就可以向下级DNS服务器发送查询请求了
-
互联网中存在根域 是真实存在的
- 根域的DNS服务器中保管着com、jp等的DNS服务器信息
- 由于上级DNS服务器保管着所有下级DNS服务器的信息,所以可以从根域开始一路往下顺藤摸瓜找到任意一个域的DNS服务器
- 根域的DNS服务器信息保存在互联网中所有的DNS服务器中,这样一来任何DNS服务器都可以找到并访问根域DNS服务器
- 分配给根域DNS服务器的IP地址在全世界仅有13个
- 根域DNS服务器的相关信息已经包含在DNS服务程序的配置文件中了,因此只要安装了DNS服务器程序,这些信息就被自动配置好了
-
一个具体的查找过程:
- 客户端首先找到最近的一台DNS服务器
- 从顶层开始向下查找,最近的DNS服务器保存了根域DNS服务器的信息,将来自客户端的查询消息转发给根域DNS服务器
- 根据域名结构,返回子域的IP地址,让客户端去子域中进行查找
1.3.4 通过缓存加快DNS服务器的响应
- 在真实互联网中,一台DNS服务器可以管理多个域的信息,因此并不是每个域都有一台自己的DNS服务器
- DNS服务器有缓存功能:
- 可以记住之前查询过的域名
- 如果要查询的域名和相关信息已经在缓存中,那么可以直接返回响应
- 接下来的查询可以从缓存的位置开始向下进行
- 当要查询的域名不存在时,“不存在”这一响应结果也会被缓存
- 需要注意的是,消息被缓存后,原本的注册信息可能会发生改变,这时缓存中的信息就有可能是不正确的
- 因此DNS服务器中保存的信息都设置有一个有效期,当缓存中的信息超过有效期后,数据就会从缓存中删除
- 在对查询进行响应时,DNS服务器也会告诉客户端这一响应的结果是来自缓存中还是来自负责管理该域名的DNS服务器
1.4 委托协议栈发送信息
1.4.1 数据收发操作概览
- 向操作系统内部的协议栈发出委托时,需要按照指定的顺序来调用Socket库中的程序组件
- 首先,服务器一方先创建套接字,然后等待客户端向该套接字连接管道
- 当服务器进入等待状态时,客户端就可以连接管道了
- 管道在连接时是由客户端发起的,但在断开时可以由客户端或服务器任意一方发起
- 创建套接字阶段 => 连接阶段 => 通信阶段 => 断开阶段
- 这4个操作都是由操作系统中的协议栈来执行的
- 通过调用Socket库中的程序组件来执行,但这些数据通信用的程序组件其实仅仅充当一个桥梁的角色,并不执行任何实质性的操作,应用程序的委托内容最终会被原原本本传递给协议栈
1.4.2 创建套接字阶段
- 描述符:用来识别不同的套接字
- 应用程序用来识别套接字的机制
- 应用程序是通过“描述符这一类似号码牌的东西来识别套接字的
1.4.3 连接阶段:把管道接上去
- 连接操作的对象是某个具体的套接字
- 当同时指定IP地址和端口号时,就可以明确识别出某台具体的计算机上的某个具体的套接字
- IP地址和端口号,客户端和服务器之间用来识别对方套接字的机制
- 如果说描述符是用来在一台计算内部识别套接字的机制,那么端口号就是用来让通信的另一方能够识别出套接字的机制
- 服务器上所使用的端口号是根据应用的种类事先规定好的
- Web 80端口
- 电子邮件 25端口
1.4.4 通信阶段:传递消息
- 调用read时需要指定用于存放接收到的响应消息的内存地址(接收缓冲区)
- 由于接收缓冲区是一块位于应用程序内部的内存空间,因此当消息被存放到内存缓冲区中时,就相当于已经转交给了应用程序
1.4.5 断开阶段:收发数据结束
- Web使用的HTTP协议规定,当Web服务器发送完响应消息之后,应该主动执行断开操作
- 在HTTP版本1.1中,有了能够在一次连接中收发多个请求和相应的方法,在这种情况下,当所有数据都请求完成后,浏览器会主动出发断开连接的操作