从输入URL到打开页面到底发生了什么
每个分层都有他的道理,这就跟JS代码加不加分号一样是很私人的事情,这里我为了方便理解就按照五层协议学习的
一张提纲挈领的图
几个问题
- 为什么网络协议要分层,这样的优缺点是什么
- 分层以后,每层有每层的协议,可以独立工作,一层的改变并不影响另一层
- 但是这样分层可能导致同样的逻辑在这层用一次,在那层用一次
- 分这么多层性能会差嘛
- 并不会,每一层层层封装最终也不过是多出来很少字节的数据,性能浪费没有想象的那么高
1 应用层
1.1 解析URL
URL (Uniform Resource Locator) 浏览网页差不多是从这一步开始,这里介绍下url的格式,这个链接的blog说的很详细,但是由于绝大多数网页都是HTTP/HTTPS协议,所以这一部分可以省略,同样,80端口号是默认的,一般也不用写,而由于http支持服务器将网页重定向,所以www也可以不用写,因此用户访问网页的时候只用键入一部分就可以了,比如https://www.mcppy.com
和mcppy.com
都可以进入同一个网站。
1.2 生成HTTP请求消息
解析完URL之后,我们就知道应该访问的目标在那里了,接下来浏览器会用HTTP协议来访问web服务器
HTTP协议:
他定义服务端与客户端交互消息的内容和步骤。
客户端发出一个request,客户端回应一个response
request报文主要包含两个部分
-
对什么(url)
-
进行怎么样的操作,这部分被称作方法,有人叫作http动词
这部分MDN有解释
整个http请求报文大概是这样的
- 第一行是请求行,包括三部分,用空格隔开
- 紧接着是报文头,是KV结构、属性名:属性值
- 待补充
response报文
待补充
1.3 向DNS服务器查web服务器的ip地址
- 因为ip地址是一串数字,很难记,所以就有了域名这个东西,但是知道ip地址才能传输数据,所以就有了DNS服务器,就跟小时候的电话本一样,知道域名可以查ip,知道ip可以查域名
- DNS是树状结构,能很快的查询到域名
1.3.1 通过解析器向dns服务器查询
向DNS服务器查web服务器的ip地址就是向dns服务器发消息,并接受服务器的响应消息。
我们电脑上有对应的dns客户端,叫做解析器,在操作系统的Socket库中,我们查ip是通过这个解析器向dns服务器发出查询,在编写浏览器等应用程序的时候,只要协商解析器程序名字+web服务器的域名就完成了对解析器的调用。调用解析器以后,是解析器向dns服务器发送潮汛消息,然后dns服务器返回响应消息,响应消息中包含查到的ip地址,解析器会取出ip地址,并将其写入浏览器知道的内存地址中。浏览器向web服务器发消息的时候,只要从该内存地址取出ip地址,并将它与http请求一起发给操作系统。
1.3.2 解析器
浏览器调用解析器的时候,浏览器本身的程序会被暂停,此时控制流程转移,当控制流畅转移到解析器以后,解析器会生成要发给dns服务器的请求,这个发送的操作是解析器委托给操作系统内部的协议栈来发送的,协议栈会通过网卡把消息发给dns服务器。
如果要访问的web服务器已经在dns服务器上注册的话,这个信息就能被找到,然后再被写入响应消息返回给协议栈,再经过解析器,写入web浏览器的指定的内存区域中。
向dns服务器发消息的时候,也要知道dns的ip地址,这个ip地址是被作为TCP/IP的一个设置事先写好了
1.4 委托协议栈发送消息
1.4.1 概览
知道ip地址以后就委托系统内部的协议栈去向这个目标ip发送HTTP请求了,
收发数据就是两台计算机之间连接了一条数据通道
做管道的关键是套接字,套接字就相当于管道两边的数据出入口,把套接字连起来就是管道了。
有以下四个阶段
- 创建套接字
- 建立通道
- 收发数据
- 断开连接
浏览器或者说是操作系统里面的Socket库并不能自己收发消息
应用程序是调用Socket库里面的组件来执行数据的收发操作,但是这四个步骤都是由操作系统的协议栈来实现的
协议栈是如何接到委托的?
应用程序调用Socket库中的应用组件,来委托协议栈,Socket就相当于一个桥梁的角色,不进行实质性操作,应用程序的委托内容会被原本的给协议栈。
1.4.2 应用程序委托收发数据的过程
应用程序通过按照一定顺序调用Socket库中特定的程序组件进行委托(这些组件就是api啦)
阶段 | 调用的组件 | 需要的参数 | 作用 |
---|---|---|---|
套接字阶段 | socket组件 | 创建套接字,返回描述符 | |
接通管道阶段 | connect组件 | 描述符,服务器ip地址,端口 |