# 网络相关笔记

# 避免浏览器自动播放文件

有时对于图片、视频,浏览器会视能力,自动为用户显示或播放。这主要是由于Web服务器在返回文件本身数据的同时,返回了一些特殊的MIME类型, 比如:image/jpeg(JPEG图像),application/pdf(PDF文档),video/mpeg(MPEG动画)。 这些MIMIE类型实际上是告诉浏览器,文件数据到底是什么,这样浏览器就能更好的为用户展示数据。 现在像图片、pdf、甚至是视频基本都是可以直接在浏览器中展示和播放的。 但是有时,我们需要浏览器为用户下载文件而不是直接播放, 而Nginx在默认配置下,会根据文件的后缀来匹配相应的MIME类型,并写入Response header,导致浏览器播放文件而不是下载, 这时需要通过配置让Nginx返回的MIME类型为下面这个类型:

application/octet-stream

这个类型会让浏览器认为响应是普通的文件流,并提示用户下载文件。可以通过在Nginx的配置文件中做如下配置达到这样的目的:

location /download/ {
    types        { }
    default_type application/octet-stream;
}

这样当Url路径中包含/download/时,MIME类型会被重置为application/octet-stream。 另外,nginx自带的MIME类型映射表保存在conf/mime.types中。

express中返回头设置这个格式,就可以文件下载:

app.use('/test', function (req, res, next) {
  res.set({
    'Content-Type': 'application/octet-stream',
    'Content-Disposition': "attachment; filename=test.txt"
  });
  res.send('Hello test!');
});

其中,Content-Disposition可以设置文件名称。

当然,也可以这样写:

app.use('/test', function (req, res, next) {
  res.type('application/octet-stream');
  res.attachment('abc.txt');
  res.send('Hello test!');
});

# http协议不同版本

# http1.1

HTTP/1.1 为网络效率做了大量的优化,最核心的有如下三种方式:

  • 增加了持久连接;
  • 浏览器为每个域名最多同时维护 6 个 TCP 持久连接;
  • 使用 CDN 的实现域名分片机制。

引入了 CDN,并同时为每个域名维护 6 个连接,这样就大大减轻了整个资源的下载时间。

这里我们可以简单计算下:如果使用单个 TCP 的持久连接,下载 100 个资源所花费的时间为 100 * n * RTT;若通过上面的技术,就可以把整个时间缩短为 100 * n * RTT/(6 * CDN 个数)。从这个计算结果来看,我们的页面加载速度变快了不少。

影响 HTTP/1.1 效率的三个主要因素:

  1. TCP 的慢启动
  2. 多条 TCP 连接竞争带宽
  3. 队头阻塞

# http2.0

HTTP/2 采用多路复用机制来解决以上1.1的问题。

多路复用是通过在协议栈中添加二进制分帧层来实现的。有了二进制分帧层还能够实现请求的优先级服务器推送头部压缩等特性,从而大大提升了文件传输效率。

它可以通过一个 TCP 连接来发送多个 URL 请求,能充分利用带宽。在 HTTP/1.1 时代,为了提升并行下载效率,浏览器为每个域名维护了 6 个 TCP 连接;而采用 HTTP/2 之后,浏览器只需要为每个域名维护 1 个 TCP 持久连接,同时还解决了 HTTP/1.1 队头阻塞的问题。

一个域名只使用一个 TCP 长连接和消除队头阻塞问题

缺陷

  • 队头阻塞。虽然解决了应用层面的阻塞,但tcp本身的丢包阻塞没有办法防止。有测试数据表明,当系统达到了 2% 的丢包率时,HTTP/1.1 的传输效率反而比 HTTP/2 表现得更好。
  • TCP 建立连接的延时。网络延迟又称为 RTTRound Trip Time)。我们把从浏览器发送一个数据包到服务器,再从服务器返回数据包到浏览器的整个往返时间称为 RTTRTT是反映网络性能的一个重要指标。在传输数据之前,我们需要花掉 3~4 个 RTT
  • TCP 协议僵化。第一个是中间设备的僵化。另一个是操作系统。

# http3.0

HTTP/3 基于UDP实现了类似于TCP多路数据流传输可靠性等功能,我们把这套功能称为QUIC协议

  • 实现了类似 TCP 的流量控制、传输可靠性的功能
  • 集成了 TLS 加密功能。减少了握手花费的RTT个数(把7次减少为3次)
  • 实现了 HTTP/2 中的多路复用功能。
  • 实现了快速握手功能

问题

  • 服务器和浏览器支持情况。
  • 系统内核对UDP优化不足。
  • 中间设备僵化,这些设备对 UDP 的优化程度远远低于TCP,据统计使用QUIC协议时,大约有 3%~7% 的丢包率。

# https

HTTPS 协议是由 HTTP 加上 TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。设计目标主要有三个。

  1. 数据保密性:保证数据内容在传输的过程中不会被第三方查看。就像快递员传递包裹一样,都进行了封装,别人无法获知里面装了什么。
  2. 数据完整性:及时发现被第三方篡改的传输内容。就像快递员虽然不知道包裹里装了什么东西,但他有可能中途掉包,数据完整性就是指如果被掉包,我们能轻松发现并拒收。
  3. 身份校验安全性:保证数据到达用户期望的目的地。就像我们邮寄包裹时,虽然是一个封装好的未掉包的包裹,但必须确定这个包裹不会送错地方,通过身份校验来确保送对了地方。

由于 HTTP 的明文传输特性,在传输过程中的每一个环节,数据都有可能被窃取或者篡改,这倒逼着我们需要引入加密机制。于是我们在 HTTP 协议栈的 TCPHTTP 层之间插入了一个安全层,负责数据的加密和解密操作。

我们使用对称加密实现了安全层,但是由于对称加密的密钥需要明文传输,所以我们又将对称加密改造成了非对称加密

但是非对称加密效率低不能加密服务器到浏览器端的数据,于是我们又继续改在安全层,采用对称加密的方式加密传输数据非对称加密的方式来传输密钥,这样我们就解决传输效率和两端数据安全传输的问题。

采用这种方式虽然能保证数据的安全传输,但是依然没办法证明服务器是可靠的,于是又引入了数字证书,数字证书是由CA签名过的,所以浏览器能够验证该证书的可靠性。

百看不如一试

可以亲手搭建一个 HTTPS 的站点,可以去 freeSSL 申请免费证书。

中文:https://freessl.cn/

英文:https://www.freessl.com/