计算机网络总结(一)

今天起开始总结与前端相关度比较大的一块内容,该部分内容大致被我分成三部分。今天的重点内容是计算机网络的基本框架认知和应用层的HTTP协议。

一、整体认知

说到计算机网络体系,我们就得从最基本的OSI参考模型说起,应用在网络架构中的五层模型分别是物理层——数据链路层——网络层——传输层——应用层。从前至后越来越远离计算机硬件而越来越接近用户看到的界面。在数据传递到另外一台机器上时,信息会从另一台机器的应用层一路往回传递。

信息是如何从芯片中的电流信号传递到页面成为我们见到的流动的有意义的值呢?在物理层由电压标识的二进制数0,1来传递电信号;在数据链路层将物理层传来的数据封装成很多帧,这些帧在数据链路层中来回传递并构成一组一组的数据包。前两层在前端工作中基本很难接触到,从网络层开始,才是前端接触到的网络知识较为密集的部分。

数据从数据链路层来到网络层之后主要的问题是如何控制数据包在多个计算机的流动路线,这时我们熟悉的IP协议就要登场了,它的主要用途是将数据包准确无误的传给对方,IP地址可以定位每一个主机的位置(MAC地址是网卡自带的唯一地址,但他不能用于定位)。知道每台主机位置后数据包就比较好传递了。

但传递数据包给某个主机之后,主机自己可能运行很多服务,我们可能不知道该把资源给谁,我们还要给不同进程分配不同资源。这个时候就进入了传输层,传输层的重点是区别目的主机的哪个进程要服务器资源,TCP和UDP作为有连接和无连接状态的两个协议做的事情就是用来处理这部分内容的,第二篇我们会细讲。

知道是哪个主机的哪个进程需要的资源后我们就可以把资源展示给用户了。这个位置有比 较多的协议,比如DNS。由于IP地址不够形象化,DNS域名解析协议就产生了,它将无意义的IP地址和有意义域名相互解析,生成类似http://www.baidu.com这样较为好记有意义的域名。但最重要的协议是HTTP,这个协议几乎贯穿了前端同学的学习生涯。于是在下面部分,我们来讲讲HTTP中的重点。

二、HTTP

超文本传输协议的主要用途是将传输层已经精确到哪个进程要使用的资源从服务器传到浏览器展示,或是从浏览器传到服务器。它基于TCP/IP协议,它在浏览器和服务器之间传递的信息称之为——报文,用于标识资源的符号是URI,资源地址用的是URL。

1.报文(HTTP通信中的基本单位,通过HTTP通信传输)

报文只是一个基本传输单位,作为请求或响应被传输的内容叫做实体。一般情况下它俩是一个东西,传输编码时才做比较细的区分。

报文有请求报文和响应报文的区别,不管是哪一种报文都分为报文首部和报文主体。比较重要的操作性较大的内容主要堆积在报文首部(报文主体可有可无),这个部分又分为:请求首部,响应首部,通用首部,实体首部。

实体首部主要是由Content相关的一些首部构成,外加这两个与实体的时间相关的首部(Expires ,Last-Modified)。

请求首部是与客户端相关的一些首部字段,响应首部是与服务器相关的一些指标,通用首部是这两者都用到的。

这几个部分的首部在google的开发者工具中可以较为详细的观察到。

简略截了一个知乎的get请求,同时还有一些从别的网址粘来的较为常用的首部,我们来看下里面的一些字段。

img

请求行:指的是图中的Request URL,Request Method,还有http版本号。

状态行:指的是图中的Status Code(状态码),引起错误或正确的原因短语,还有http版本号。

通用首部:

Cache-control: no-cache,no-store // 缓存资源是否接收和返回(这条是说不能从缓存中返回过期的资源,并且请求中包含机密信息)

Date: Fri, 20 Dec 2019 01:37:32 GMT

Pragma: no-cache // 客户端不接受缓存资源(知乎有这个字段应该是使用了不同的HTTP协议版本,为了保证缓存资源一定不会被接受)

实体首部:

Content-Type: (text/html) (application/json) (multipart/form-data)

// 这部分用于表示报文主体的对象类型。 multipart 这是一种多部分对象集合 form-data,byteranges 。在 MIME 扩展中会使用一 种称为多部分对象集合(Multipart)的方法,来容纳多份不同类型的数据。application指定二进制文件。text是文本文件。

Content-encoding: br

Connection: keep-alive // 逐跳首部字段, 连接管理(逐跳首部字段: 在此类别中的首部只对单次转发有效,会因通过缓存或代理而不再转发 )

img

请求首部:

Referer: https://www.solerji.top/

// 原始资源URI。Referer头允许服务器识别人们访问他们的位置,并且可以使用该数据进行分析,记录或优化缓存。

Accept-encoding: gzip, deflate, br // 优先的内容编码

Accept-language: zh-CN,zh;q=0.9 // 优先的语言

User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36

// 包含允许网络协议对等方标识请求软件用户代理的应用程序类型,操作系统,软件供应商或软件版本的特征字符串。

Host: localhost:8080 // 请求资源所在服务器

响应首部:

Server: nginx // 描述服务器

Etag: “5dd75c86-72”

// 所述ETag HTTP 响应报头为资源的特定版本的标识符。它允许缓存更高效,并节省带宽,因为如果内容没有改变,Web 服务器不需要发送完整的响应。另一方面,如果内容发生了变化,etags 有助于防止资源的同时更新互相覆盖。

Vary: Accept-Encoding // 代理服务器缓存的管理信息(当代理服务器接收到带有 Vary 首部字段指定获取资源的请求 时,如果使用的 Accept-Language 字段的值相同,那么就直接从缓存返回响应。反之,则需要先从源服务器端获取资源后才能作为。)

还有两个较为常用的是设置cookie时使用的首部字段:

set-cookie(响应首部):开始状态管理时使用的cookie信息/cookie(请求首部):服务器接收到的cookie

2.URI/URL

统一资源管理符和统一资源定位符的关系应当这样理解,URL用定位的方式实现URI。URL本身的范围要比URI小一些,一些表示邮箱地址和电话信息的:mailto:http://xxxxxxx.com,tel:+1-816-555-1212,对资源有一定的标识意义的符号都是URI,但其中只有提供访问机制的才能称之为URL,也就是说,一定要定位到某处才能成称之为统一资源定位符。

3.REST

这里拿出三个问题来讨论:

(1)为什么要有REST?

客户端和服务端在发起资源请求时对资源的一定标识和限制,进而将标识和限制具象化成几个专有名词。这个设计思想在我理解就是起名+规定这个名字可以干啥。它出现的原因是为了规范化整合资源。

(2)REST思想在前端常见的应用方向?

就是RESTful风格的一些产物:

URL,状态码

(3)REST有什么缺点

任何规则都有同样的弊端,那就是对于实际业务总是冗余或者缺失的。制定规则之初增删改查也许就够用,命名规则也许就清晰。但对于庞大的工程来说,怎么删,怎么改,怎么查还有较为细致的区分;对于小工程而言put的作用和post好像也不一定有多大区别。

笔者看来如同协议会随网络发展更新,那么规则也应根据需求制定。

4.HTTPS

由于HTTP存在的一些问题,HTTPS才得以广泛应用,它的问题在于:

(1)请求信息明文传输,容易被窃听截取。

(2)数据完整性未校验,容易窜改。

(3)并不验证对方身份,存在冒充风险。

HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。SSL协议是在TCP,IP协议和HTTP协议中间的一道墙,TCP/IP协议族的工作机制导致这些协议均可能被窃听。

HTTPS如何解决HTTP存在的这些问题的呢?

(1)将明文加密,HTTPS使用了共享密钥加密和公开密钥混合加密的方式。

(2)一些保证数据完整真实的证书,例如:验证公钥正确性的CA证书。以此保证数据是原始数据而未被替换。发送数据时附加MAC报文摘要,保护报文完整性。

(3)SSL客户端认证

当然HTTPS自身也有一些缺点,很多公司囿于这些缺点而继续使用HTTP。

(1)HTTPS协议多次握手,导致页面的加载时间延长;

(2)HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗;

(3)申请SSL证书比较贵。

(4)SSL涉及到的安全算法会消耗 CPU 资源,对服务器资源消耗较大。

5. HTTP服务瓶颈产生的其他通信方式

HTTP的某些标准在实现网站在短时间大量内容更新的需求上显得很无力。

例如:

一条连接上只能发送一个请求。

只能让客户端作为请求的开始,而且客户端只能接收响应。

首部信息并不能自己压缩后传递。传输时会带来时间和资源的损失。

于是产生了以下几种解决方案:

a. 异步通信

(1)ajax

它利用了js和DOM操作达到局部web页面替换加载的异步通信手段。核心技术是(XMLHttpRequest )。它相当于将请求由一整个页面的全部请求分块成为n部分请求,一定程度上提升了浏览速度。但是它没有改变HTTP的弊端,而且还是会有一次性发好多个请求的情况产生,如果对请求先后有要求还会形成令人讨厌的回调地狱。

(2)axios

在vue2.0后,由ajax衍生出的一个基于Promise用于浏览器和nodejs的HTTP客户端。基本原理和ajax一致,只是做了一个封装,支持一些并发接口,做了一些信息安全处理。

在以上两个基础上还出现了 async&await,仅只是简化代码和进一步封装就不细说。

b. websocket

它是基于HTTP的一种全双工通信方式。它的出现真实的改变了HTTP的一些弊端。

在客户端连接成功后,服务端和客户端均可以接收(发送)彼此的消息。它首部信息比较小,而且是一个持续连接状态,就很好的减少了传输和连接过程的开销。

一个websocket请求的传输报文首部:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    Request URL:ws://192.168.0.122:9090/file_sockjs/null
Request Method:GET
Status Code:502 Bad Gateway
(正常情况下就会返回101,因为是一种持续连接状态)
Response Headersview source
Connection:keep-alive
Content-Length:559
Content-Type:text/html; charset=utf-8
Date:Fri, 20 Dec 2019 05:50:52 GMT
Server:nginx/1.x.0
Request Headersview source
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.9
Cache-Control:no-cache
Connection:Upgrade
Host:192.168.0.x:xxxx
Origin:http://localhost:8080
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:O49IqTjekYel76BuIQWrNA==
Sec-WebSocket-Version:x
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36

由于没有具体使用过coment和spdy,HTTP2.0仍在研究过程中,这里就不加评论,后面如果涉及到再回来补上。

(推荐一本叫《图解HTTP》的书,这本书讲解的内容很透彻,感兴趣可以去看看)