前端网络协议和浏览器通信

06-01 1031阅读

网络分层模型和应用协议

分层模型

分层的主要目的就是通过通过分拆工作将网络通信简单化,官方解释:网络分层就是将网络节点所要完成的数据的发送或转发、打包或拆包,控制信息的加载或拆出等工作,分别由不同的硬件和软件模块去完成。

分层模型发展史如下:

最初为TCP/IP四层网络模型:物理链路层->网络层->传输层->应用层

然后推出了教科书上的贼标准的OSI七层网络模型:物理层->数据链路层->网络层->传输层->会话层->表示层->应用层

最后是大家广泛约定并使用的五层网络模型:物理层->数据链路层->网络层->传输层->应用层

物理层:负责物理传输的电子设备,实质为光纤、电缆等等用来将设备连在一起的东西

数据链路层:mac地址、交换机、网卡、驱动程序等,负责数据帧和二进制之间的转换,主要协议ARP、RARP

网络层:路由协议、地址解析等,这类数据包的事情都是网络层负责的,换句话说,网络层主要负责地址解析和路由,选择传输路径。TCP/IP协议中IP属于网络层;IPX/SPX协议中IPX也属于网络层,其他还有ICMP、IGMP等

传输层:数据传输,即传输层负责获取全部信息,提供端对端的通信管理,传输控制协议有TCP(传输控制协议)/UDP(用户数据协议)。

应用层:顾名思义,应用层专门用于应用程序。应用协议指示网络应用的一个组成部分,包括http(万维网服务)、ftp(文件传输)、smtp(电子邮件)、ssh(安全远程登录)、DNS(域名解析)等

应用协议

首先了解一些协议基础,比如资源标识符

资源标识符-URI/URL

URI

统一资源标识符,是用于唯一标识互联网或本地资源的字符串,核心功能是通过标准化语法和协议实现对资源的定位或命名,是资源标识的抽象标准。URN(资源的名称)和URL(资源的位置)都是URI的具体实现形式之一。URI的组成结构如下:

scheme:[//authority][/path][?query][#fragment]

‌Scheme(方案):定义访问协议(如https、ftp)。

前端网络协议和浏览器通信
(图片来源网络,侵删)

‌Authority‌:通常为主机名(如www.example.com)和端口号(可选)。

‌Path/Query‌:资源路径和查询参数(如/docs/index.html?lang=en)

前端网络协议和浏览器通信
(图片来源网络,侵删)

URL

本质就是一个格式固定的字符串,用于获取资源,组成结构同上

前端网络协议和浏览器通信
(图片来源网络,侵删)

其中:schema、authority、path是必须有的,有时候端口可忽略,例如http协议默认忽略80端口,https协议默认忽略443端口,query非必须,多个query可以用&链接

例如:http://a.com:3000/b/detail?id=1#name1

这段字符串传递了如下信息,使用http(schema)协议,从a.com(authority)这台计算机的3000端口的程序,寻找/b/detail(path)这个服务中id=1(qurey)的部分

这个部分的重点是程序,在计算机中找到使用对应端口的程序后,通过程序内部逻辑去找到符合/b/detail(path)的服务,此时,程序会将设置好的/b/detail(path)对应的‘值’返回给用户,/b/detail(path)不代表一个文件,仅代表一个程序内部的逻辑条件

前端vscode中用的live server插件也是这个逻辑,通过该插件在浏览器打开html文件时,该插件的程序逻辑就是在当前文件列表中找到对应路径的文件并将其内容反馈到浏览器上,这种用来将文件和路径进行对应的程序,也叫做静态资源服务器,所以,不是所有的/b/detail(path)部分都是用来对应文件的,那只是众多程序中的一种罢了

拓展:dataUrl,就是一个包含了全部资源信息的url,所有支持url的地方, 一定也支持dataUrl,所以除了使用eval(),也可以利用dataUrl实现动态的js代码,例如在script标签中src="一个dataUrl"等。

接下来进入协议部分

应用层协议

学习协议前提—搞清楚什么是客户端,什么是服务器:

简单来说,一次交互中,发出请求的就是客户端,发出响应的就是服务端

HTTP

该协议用于规定传递的消息的模式和格式

HTTP消息传递模式(请求-响应):客户端发请求->服务端接受请求->服务端发出响应->客户端接受响应,至此一次交互结束;

HTTP消息传递格式:

请求部分:请求行、请求头、请求体

**请求行**:请求方法(可自定义,本质上只是个标记,怎么定义都可以)  路径(包括query)  HTTP协议版本
示例:
GET /api/test?id=1 HTTP/1.1
**请求头**:包括域名等配置
示例:
Host: www.baidu.com
Content-Type: application/x-www-form-urlencoded
//请求头和请求体之间必须有两行换行
**请求体**:请求参数(有多种拼接方式,具体怎么拼接受请求头中的Content-Type属性控制)
示例1:
username=user1&userid=1
示例2(当Content-Type值为application/json时)
{
	"username":"user1",
	"userid":"1"
}
示例3(当Content-Type值为multipart/form-data;boundary=0000时,这个格式一般用于传输图片,优点在于可直接传输图片二进制而无需转成base64)
--0000
Content-Disposition:form-data; name="avatar"
filename="1.png"
Content-Type:img/jpeg
这里放置图片二进制
--0000

响应部分:响应行、响应头、响应体

响应行:HTTP协议版本 状态码 
状态码大概有五个分类:1xx一般返回信息,代表服务器收到了请求但是需要请求者继续执行操作;2xx代表请求成功被接受并处理;3xx表示请求重定向,其中301为永久重定向,302为暂时重定向;4xx代表客户端错误,一般是请求语法写错了或无法完成请求;5xx代表服务器错误,表示服务器处理请求时发生了错误
示例:HTTP/1.1 200 OK
响应头:一些配置,例如Content-Type代表响应体的格式,Content-Length代表响应体的字节数
示例:
Content-Type:text/html
Content-Length:233
响应体

HTTP使用很广泛,但是不安全:1.明文传送数据 2.缺乏数据完整性校验。这会导轨攻击者可以很轻易的窃取、篡改、插入数据。

HTTPS

很多时候我们会将HTTPS和HTTP放一起对比,实际上HTTPS就是一个更安全的HTTP通道,它是在HTTP协议的基础上,加入SSL/TLS协议进行加密和身份验证,HTTPS的更高安全性就来自于SSL/TLS,也就是说HTTPS=HTTP+SSL/TLS(一般HTTPS端口号是443)

HTTPS连接建立过程:一个双向奔赴的SSL/TLS握手过程

1.客户端发出链接请求,将自己支持的加密算法列表发给服务器
2.服务器选一个加密算法,并将自己的服务器证书一起发给客户端
3.客户端验证服务器证书有效性 ,验证通过则生成预主密钥,并用服务器公钥加密以后发给服务端
4.服务端使用私钥解密预主密钥,双方生成会话秘钥,对后续通信加密
至此,加密通道建立,通信开始

SSL/TLS

SSL也叫安全套接层,用来保护网络通信安全,它的核心就是建立加密通道加密、身份验证

TLS也叫传输层安全,是SSL的标准化升级版本,安全性和性能相较SSL都更强劲

SSL/TLS的工作方法,就是上面HTTPS里写的 ‘HTTPS连接建立过程:一个双向奔赴的SSL/TLS握手过程’

SSH

也叫安全外壳协议,一般用来远程登录,默认端口22,对于用户验证,它有公钥(公钥-私钥对应验证)和密码(用户名-密码对应验证)两种方法:

1.公钥认证:

1.客户端将用户名和公钥发给服务器
2.服务器发送一个随机数给客户端
3.客户端使用私钥对随机数进行签名,发给服务器
4.服务器使用公钥验证签名,并返回认证结果

2.密码认证:

1.客户端将用户名发给服务器
2.服务器向客户端请求密码
3.客户端将加过密的密码发给服务器
4.服务器验证密码并返回结果

smtp

简单邮件传输协议,顾名思义,是一个用来发电子邮件的协议。那么它是如何发送和传递邮件的?

建立连接
1.客户端连接服务器SMTP端口,一般是25
2.服务器表示服务就绪:发送状态码220给客户端
3.客户端告诉服务器自己域名:发送HELLO/EHLO给服务器
4.服务器表示命令成功:返回250状态码给客户端
发邮件
1.客户端指定发件人邮箱:发送MAIL FROM:给服务器
2.服务器表示命令成功:返回250状态码给客户端
3.客户端指定收件人邮箱:发送PCPT TO:给服务器
4.服务器表示命令成功:返回250状态码给客户端
5.客户端输入邮件内容
6.服务器表示知道客户端开始输入邮件了:返回354
7.客户端把写完的邮件发给服务器
8.客户端告诉服务器我邮件写完了:用单独一行的句点表示邮件输入结束
9.服务器表示邮件接收成功:返回250状态码给客户端
关闭连接
1.客户端请求关闭连接:发送QUIT命令
2.服务器表示链接已关闭:返回状态码221

DNS

本质是将域名转换为IP的一个分布式系统,端口号53,常用来解析域名,也相当于更全的、网络端的HOSTS文件。可以用它进行域名解析、指定邮件服务器地址、负载均衡、域名重定向等等

传输层协议

TCP

很传统且常见的传输控制协议,也是网络核心协议之一;用来提供一个可靠的、面向连接的、基于字节流的数据传输服务

TCP是一个数据传输服务,其服务原理就是基于三次握手(建立连接)和四次挥手(终止连接)

SYN:同步请求
ACK:确认
FIN:结束请求
三次握手流程:
1.客户端请求建立连接:发个SYN包(同步请求)给服务器
2.服务器表示同意建立连接:服务器收到SYN包(同步请求)以后,回复一个SYN-ACK包(同步确认)给客户端
3.客户端告诉服务器连接已建立:客户端收到SYN-ACK包(同步确认)以后,最后发一个ACK包(确认)给服务器
至此,连接建立完成,开始传数据
四次挥手流程:
1.客户端发一个结束请求,请求关闭连接:发一个FIN包给服务器
2.服务器表示确认:服务器收到FIN包以后,回一个ACK包给客户端
3.服务器发一个结束请求,表示自己也要关闭连接了:服务器发一个FIN包给客户端
4.客户端表示确认:收到FIN包以后,回一个ACK包,表示确认
至此,连接关闭

UDP

一个简单的无连接协议,也就是不需要连接就可以发数据,主打快速;发数据只需要两步,全程无反馈,无确认:

1.客户端直接给服务器发一个UDP数据包

2.服务器接收数据包

网络层协议

IP

网际互联协议,本质是一个网络信息传送协议,用来为主机提供一种端对端的、非连接、不可靠的数据包传输服务,源端只管发就可以,至于目标端是否收到,则由上层协议例如TCP负责检查。

IP依赖IP地址和路由器,主要提供两个服务:1.信息传送 2.信息分割、信息重组

接下来,我们要先了解三个概念:

1.MTU,最大传输单元,所有网络数据帧都有MTU的限制

2.IP地址:所有网络设备都有且仅有一个IP地址,具有唯一性,且IP信息包必须包含IP地址

3.路由器:负责选择路径,并根据网络地址进行转发,IP信息包是必须经过路由器进行转发的

那一个IP包从源端传输到目标端这个过程中都可能发生什么呢?

1.如果该IP包的大小超过了出口链路的MTU,则需要先进行IP分片,IP协议会在路由器上将IP包的数据部分分解成小片段,分别发送,目标端收到后再将其进行分段重组,重组成一个完整包再交给上层协议处理
2.传输过程中,经过路由器转发时,根据目标端是否与本地路由器直接相连,我们有两种模式可选:直接交付(单人短跑,路由器直接把IP包交给目标端);间接交付(团队跑接力赛,路由器通过路由表查找路由信息,并将IP包转发给必经的下一个路由器)
3.不考虑过程,但从端对端结果看,我们有三种传输模式可选:单点(1v1)、多点(1vn,这个n可以指定)、广播(1vn,和多点区别是广播没法指定目标端ip,会无差别的把信息发给该网络内所有设备)

浏览器通信

用户代理

浏览器两个核心能力:

1.自动发出请求

当用户做了页面操作、表单提交、页面刷新、页面link、img、script、audio、video元素HTML解析时,浏览器会自动发出请求

浏览器请求中,我们最常看到的就是POST请求和GET请求,那这两种请求到底有什么差别呢?

从HTTP 7231规范来讲,不同请求方法之间其实只有语义的差别,表达客户端这次请求的目的,但由于各大服务器的约定俗成,导致目前开发层面有了许多的约束:

1.浏览器发送GET请求是不会附带请求体
2.由于不附带请求体,GET请求一般只能将信息放入请求path/query中,导致其能传递的信息量很有限;而POST请求无此限制
3.由于GET一般将信息放入path/query中,在易于分享和重现页面的优点之外,存在着暴露数据的缺点,安全性差,所以对于敏感数据一般不会选择GET
4.GET请求只能传递ASCII数据,所以一旦碰到中文等非ASCII数据,则需进行编码,POST无此限制
5.POST请求不会被保存到浏览器的历史记录中,历史记录和刷新页面的本质都是复现请求,GET请求由于其易分享和重现的特性,是可以直接复现的,但是复现POST请求时会进行数据的重复提交,可能与用户预期相悖,这也是产生第六条的根本原因
6.GET请求在浏览器页面刷新时无提示,而POST请求会提示是否重新提交

2.自动解析响应

浏览器会解析哪些响应呢:响应码(例如301/302),浏览器会自动识别并对一些特殊响应码进行处理;Content-Type,根据响应头中该属性的不同值,浏览器会做出不同处理,例如:Content-Type:text/html,浏览器会将响应体作为页面渲染、Content-Type:text/javascript,浏览器会使用js执行引擎将响应体解析并执行、Content-Type:text/plain,纯文本,浏览器直接将响应体显示到页面、Content-Type:text/css,浏览器会把其看做样式、Content-Type:image/jpeg,浏览器会把其看做图片、Content-Type:application/octet-stream,二进制数据,触发浏览器下载

Content-Disposition也可以出发浏览器解析响应,例如Content-Disposition:attachment,附件,一样触发浏览器下载等等

拓展:form表单最大的用处就是用来发送请求,利用其提交事件,它会自动监听用户操作,能自动区分输入法的回车和提交回车,可以大大减少在提交操作判定处理方面的代码量。如下例,在浏览器中,点击表单的提交按钮后,浏览器会自动发送下方格式的POST请求,所以我们可以这么理解,form中action和method对应的就是请求行和请求头,示例中Input的name对应的就是请求体的属性名,Input的value就是请求体该属性名对应的值,button则是用来触发浏览器自动解析并发送该请求

	账号
	密码
	提交

上方表单可以解析成如下请求

POST /api/user/login HTTP/1.1
Host:  test.login.com
Content-Type: application/json
{
	"longinId":"admin1",
	"loginPwd":"233"
}
浏览器的通信流程

当在浏览器输入一个地址后,发生了哪些事?

1.浏览器补全url地址,例如根据当前页面的协议补全url中缺少的协议部分(http、https等)

2.对地址中的非ASCII字符自动完成url编码

3.发出请求

4.根据响应中的Content-Type类型,对响应体的数据进行解析、处理、展示;

注:页面的初始请求的响应数据一般是一个HTML文档,此时浏览器会进入我之前文章讲的浏览器渲染过程及原理。在浏览器渲染过程中,始终会穿插3和4这两步,比如当浏览器解析HTML文档发现了link元素时,会发出请求,此时会在响应中获取到css代码,发现img元素,一样发出请求并在响应体中获得图片内容等;

AJAX

1.AJAX是什么?

全称Asynchronous Javascript And XML,本质就是在web应用程序中用js向服务器异步发送一个XML格式的请求。

为什么是异步呢?因为js单线程,不异步很容易卡死,具体还是回归到我之前文章讲的浏览器渲染过程及原理的异步部分

2.AJAX代码实现方式:XHR(XMLHttpRequest)、Fetch;这两个实现方式有什么区别呢?

功能XHRFetch
请求能力
请求取消
获取响应能力
监控请求进度×
监控响应进度
Service是否可用×
控制cookie携带×
控制重定向×
自定义referrer×
×
API风格EvementPromise
活跃度停止维护和更新持续维护更新中

拓展:axios是基于XHR实现的一个库,所以XHR就是axios的能力边界,而umi-request是基于fetch实现的库,所以fetch是它的能力边界

跨域

什么是跨域

什么是源?

源=协议+地址+端口

所以,同源就是协议+地址+端口部分完全一样;协议+地址+端口但凡有一样不同,就是异源

同源策略:一种浏览器安全机制,放行同源的资源,限制异源的资源

什么时候会跨域?跨域一定会有问题吗?

浏览器运行页面时,会发出很多请求,当页面源与目标源一致,则为同源请求,否则为异源请求(跨域请求),跨域不一定有问题,只有因为跨域造成了开发限制,才是问题

浏览器中的跨域报错原因是什么?

浏览器对于页面标签元素的跨域请求限制轻,而对于AJAX发出的跨域请求严厉限制。当利用js发出跨域请求时,浏览器首先拿到该请求,并将请求发送出去,随后浏览器拿到响应,并对响应进行校验,校验通过则正常传递响应,检验不通过则报错引发跨域问题

怎么解决跨域

一.CORS

一套帮助浏览器判断检验是否通过的规则,其判断规则,就是看服务器返回的响应中是否明确表示了允许通过,表示了则校验通过,除此以外的任何情况都视为不通过。

CORS中有两种请求:简单请求、预检请求。针对这两个请求规则也是不同的

一、简单请求需要满足以下三个条件:
1.请求方法是POST/GET/HEAD
2.请求头使用的是浏览器默认的,没有被开发者改动过
3.如果设置了Content-Type,那它的值只能是‘text/plain’、‘ultipart/form-data’、‘application/x-www-form-urlencoded’中的一个
如果不能同时满足简单请求的三个条件,那它就是个预检请求
二、对于简单请求,CORS判断是否通过规则如下:
1.CORS在请求头中带上Origin字段,值为当前页面源,例如Origin:www.example.com,浏览器传递给服务器
2.服务器如果允许通过,则会在响应头中带上Access-Control-Allow-Origin字段,且该字段的值为*或者与1中的Origin值相同,例如Access-Control-Allow-Origin:*或Access-Control-Allow-Origin:www.example.com,此时浏览器会判断检验通过,直接放行,除此以外,服务器返回的其他情况的值均会被浏览器视作不允许通过
1和2简单讲就是请求头中的Origin与响应头中的Access-Control-Allow-Origin一致或者Access-Control-Allow-Origin:*(不建议这么配置,因为携带cookie的请求是不允许这么配置的)就通过,不一致就不通过,Access-Control-Allow-Origin这个是服务器返回的,如果服务器是自己人,那是完全可以通过后端代码配置的
三、对于预检请求,CORS判断是否通过规则如下:
1.先向服务器发送一个预检请求,请求头中会自动带上以下三个参数:Origin:当前页面源;Access-Control-Request-Method:请求方法;Access-Control-Request-Headers:请求头中被开发者改动的值
2.服务器响应:如果允许通过,会在响应头中带入以下四个属性:Access-Control-Allow-Origin:允许通过的源;Access-Control-Request-Methods:允许通过的请求方法;Access-Control-Request-Headers:允许通过的请求头中被开发者改动的值;一般服务器允许通过时这三个属性的值是和请求头中的相同的,第四个属性是Access-Control-Max-Age:缓存时间,也是允许通过最长时间,只要在缓存时间内,这个请求浏览器就无需再问服务器,直接通过就可以。其他情况都代表服务器阻止通过
3.如果2返回的结果是阻止通过,那本次请求到此终止。如果2返回的结果是通过,那接下来浏览器会发出一个简单请求
4.服务器返回响应结果,至此一次完整的预检请求结束

特殊情况:

1.携带了cookie的请求

如果要允许该携带了cookie的跨域请求通过,服务器需在响应头中加上如下属性:Access-Control-Allow-Credentials:true。如果服务器没有在响应头加上该属性,及时请求头携带了cookie,也会被拒绝跨域;而且,对于这种携带cookie的跨域请求,上文简单请求和预检请求通过规则里面响应头返回的Access-Control-Allow-Origin属性,是不允许为*的

AJAX跨域请求默认不携带cookie,如果需要需要手动配置

//使用xhr携带cookie
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
//使用fetch携带cookie
fetch(url,{
	credentials: "include"
})

2.获取不到响应头中某些信息

浏览器控制台可以看到该信息,但通过js却获取不到,那此时可以通过设置服务器响应头的Access-Control-Expose-Headers属性,将它的值设置为自己需要获取的属性名,就可以访问到了

二、JSONP

本质就是利用浏览器对于页面标签元素中的跨域请求的弱限制,不用AJAX去发送跨域请求,而是直接使用标签元素发送请求,仅能发送GET请求,且有安全隐患,举个例子:

	//封装一个jsonp发送跨域请求的函数
	function request(url){
		return new Promise((resolve) => {
			//拿到跨域请求结果
			window.callback = function (res) {
				//我们只需要结果,并不需要将该元素实际插入html中
				script.remove()
				resolve(res);
			};
			//构造一个发出跨域请求的标签元素
			const script = document.createElement('script');
			script.src = url;
			document.body.appendChild(script);
		})
	}
	//调用封装好的跨域请求
	request('跨域请求url').then((res)=>{console.log(res)})

三、代理

当无法修改服务器响应数据,则可以考虑代理,实质就是利用代理服务器进行一层转发,避过浏览器和外服务器的直接沟通,浏览器发请求->代理服务器转发请求->外服务器。

跨域只会发生在浏览器中,代理服务器使我们可以控制的,代理服务器和外服务器间不存在跨域问题,所以至此,跨域问题迎刃而解

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码