基础知识-网络

481 阅读41分钟

Ajax

Ajax使用

原生ajax使用

XMLHttpRequest,ajax核心api get 请求

    const xhr = new XMLHttpRequest()
    xhr.open('GET', '/data/test.json', true) //true表示异步
    xhr.onreadystatechange = function () {
      if(xhr.readyState === 4) {
        if(xhr.status === 200) {
          alert(xhr.responseText)
        }
      }
    }
    xhr.send(null)

post 请求

    const xhr = new XMLHttpRequest()
    xhr.open('POST', '/login', true) //true表示异步
    xhr.onreadystatechange = function () {
      if(xhr.readyState === 4) {
        if(xhr.status === 200) {
          alert(xhr.responseText)
        }
      }
    }
    const postData = {
      userName: 'zhangsan',
      password: 'xxx'
    }
    xhr.send(JSON.stringify(postData))

jQuery方式使用

$.ajax({
    //请求方式
    type: "POST",
    //请求的媒体类型
    contentType: "application/json;charset=UTF-8",
    //请求地址
    url: "http://127.0.0.1/admin/list/",
    //数据,json字符串
    data: JSON.stringify(list),
    //请求成功
    success: function(result) {
        console.log(result);
    },
    //请求失败,包含具体的错误信息
    error: function(e) {
        console.log(e.status);
        console.log(e.responseText);
    }
})

fetch方式使用

浏览器的兼容没有XMLHttpRequest支持好

fetch('http://example.com/movies.json')
.then(function(response) {
    return response.json()
 })
 .then(function(myJson) {
    console.log(myJson)
 })
}

axios主流

axios中文文档

// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')   
    .then(function (response) {     
        console.log(response);   
    })   
    .catch(function (error) {    
        console.log(error);   
    });  
    // 上面的请求也可以这样做 
    axios.get('/user', {     
        params: {       
        ID: 12345    
        }   
    })   
    .then(function (response) {     
        console.log(response);   
    })   
    .catch(function (error) {     
        console.log(error);   
    }); 

Ajax的api

xhr.readyState

  • 0(未初始化)还没有调用send()方法
  • 1(载入)已调用send()方法,正在发送请求
  • 2(载入完成)send()方法执行完成,已经接收到全部响应内容
  • 3(交互)正在解析响应内容
  • 4(完成)响应内容解析完成,可以在客户端调用

xhr.status

  • 2xx- 表示成功处理请求,如200
  • 3xx- 需要重定向,浏览器直接跳转,如 301(永久重定向:直接访问b),302(临时重定向,每次都先访问a,获得302状态码后跳转到b),304(资源未改变,浏览器使用本身缓存的资源)
  • 4xx- 客户端请求错误,如404(请求地址错误),403(没有权限)
  • 5xx- 服务器端错误

使用promise封装ajax

    //函数封装
    function ajax(url) {
      const p = new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              resolve(JSON.parse(xhr.responseText));
            } else if (xhr.status === 404) {
              reject(new Error("404 not found"));
            }
          }
        };
        xhr.send(null);
      });
    }
    // 使用
    const url = "/data/test1.json";
    ajax(url)
      .then((res) => console.log(res))
      .catch((err) => console.log(err));

跨域

同源策略

概念

参考 同源策略是一种约定,它是浏览器最核心最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS(跨站脚本攻击)、CSRF(跨站请求伪造)等攻击。同源是指当ajax发送请求时,浏览器要求当前网页和server端必须同源,即协议,域名,端口,三者必须一致。
例子

协议一个是http,另一个是https;域名一个是a.com,另一个是b.com;端口一个是8080,另一个是80;不同源
//前端
http://a.com:8080/
//后端
https://b.com/api/xxx

有三个标签允许跨域加载资源

<img src=跨域的图片地址 />
<link href=跨域的css地址 />
<script src=跨域的js地址></script>
<img /> 可用于统计打点,可使用第三方统计服务
<link /><script>可使用CDN,CDN一般都是外域
<script>可实现JSONP

实现跨域

前提

  • 所有的跨域,都必须经过server端允许和配合
  • 未经server端允许就实现跨域,说明浏览器有漏洞,危险信号

JSONP

参考 利用<script>标签不受同源策略约束的特点,使得网页可以获得其他来源的响应数据。同时JSONP请求需要后端的配合才可以。

JSONP优缺点

JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题、缺点是仅支持get方法具有局限性,不安全可能会遭受xss攻击。

JSONP的实现流程

  • 先声明一个用于接收数据的全局函数如show。
  • 创建一个<script>标签,它的scr等于跨域的url地址,并且在这个地址后面拼接需要回调的函数名如?callback=show。
  • 服务器接收到请求后,需要进行特殊的处理:将需要返回的数据作为函数的参数,再将整个函数的调用返回给客户端。例如:传递进去的函数名是show返回show('收到请求')
  • 最后客户端收到数据,执行回调。 原理
// 前端
  <script>
    window.abc = function (data) {
      console.log(data)
    }
  </script>
  <script src="http://localhost:8002/jsonp.js?username=xxx&callback=abc"></script>

// 后端返回数据
abc(
    { name: 'xxx' }
)

手写JSONP

let script = document.createElement('script');
script.type = 'text/javascript';

script.src = 'https://query.asilu.com/weather/baidu?city=北京&callback=jsonp';//获取北京的天气情况
document.head.appendChild(script);//创建并添加script标签到<head>下

// 回调执行函数
window.jsonp =  function (res) {
    console.log(res);//打印jsonp返回的信息
}

jQuery版

$.ajax({
  url: 'https://query.asilu.com/weather/baidu?city=北京',
  dataType: 'jsonp',//jsonp方式的跨域
  jsonpCallback: 'fn',//后端需要调用的函数名称
  success: function (data) {//成功返回后调用的函数
    console.log(data)
  }
})

CORS-服务器设置http header

后端通过access-control-allow-origin设置允许访问的域名

    response.setHeader("Access-Control-Allow-Origin", "http://localhost:8011");//设置允许访问的域名
    response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
    response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")
    //是否允许携带cookie
    response.setHeader("Access-Control-Allow-Credentials", "true");

http缓存(浏览器缓存)

http缓存介绍

浏览器在第一次访问网站后再次访问,有些资源是不变的,如果把这些不变的资源保存起来,就可以减少网络请求的次数和体积,提高网页加载的速度。一般缓存的是静态资源(js css img)

http缓存策略(强制缓存+协商缓存)

参考

强制缓存

image.png

  • 浏览器第一次访问的时候,服务端会先判断这个资源是否需要被缓存,如果需要会在Response Headers中加入Cache-Control,返回给浏览器。
  • 当浏览器再次访问时,会先根据本地缓存资源的 headers 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。 Cache-Control

Cache-Control 是 http1.1 时出现的 headers 信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。

Cache-Control的值

  • max-age 最大过期时间
  • no-cache 不用本地强制缓存,正常发起请求
  • no-store 禁止使用缓存,每一次都要重新请求数据
  • private 只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存
  • public 可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器

Expires

关于Expires,同在Response Headers中,同为控制强制缓存,已被Cache-Control代替。 该字段是 http1.0 时的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。

强缓存内存

  • 强缓存不会向服务器发送请求,直接从缓存中读取资源
  • 请求返回200的状态码
  • 在chrome控制台的network选项中可以看到size显示from disk cache或from memory cache。

from memory cache代表使用内存中的缓存,from disk cache则代表使用的是硬盘中的缓存,浏览器读取缓存的顺序为memory –> disk。在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。

image.png

协商缓存

协商缓存和强缓存的区别在于,强缓存不需要经过服务器,而协商缓存需要经过服务器,协商缓存有两种一种是最后修改时间,另一种是Etag
Last-Modified(最后修改时间)

image.png

  • 当浏览器第一次请求时,服务器如果判断当前资源可以被缓存,那么在返回资源的同时,在Response Headers中添加 Last-Modified 属性指出资源最后一次修改的时间。
  • 浏览器在接收到Last-Modified时,就会将这个属性值记录下来,同时缓存该文件。
  • 当浏览器再次发起请求时,会在Request Headers中添加一个 If-Modified-Since 的属性,属性值和上一次返回的 Last-Modified 的值一样。
  • 当请求发送到服务器后服务器会通过这个属性来和资源的最后一次的修改时间进行比较,以此来判断资源是否做了修改。如果资源没有修改,那么返回 304 状态码,让浏览器使用本地的缓存。如果资源已经被修改,则返回最新的资源和新的Last-Modified
  • 使用这种方法有一个缺点,就是 Last-Modified 标注的最后修改时间只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,那么文件改变了但是 Last-Modified 却没有改变,这样会造成缓存命中的不准确。

Etag
所以http 提供了另外一种方式, Etag 属性,每当文件被修改时,就会重新生成一个新Etag值,这样一来缓存的命中就更加准确。Etag的执行过程和Last-Modified基本一致 image.png

  • 当浏览器第一次发送请求时,服务器如果判断当前资源可以被缓存,则在返回资源的同时,在Response Headers中添加 Etag 属性。
  • 当浏览器再次发送请求时,浏览器会在Request Headers中添加一个 If-None-Match 属性,这个属性的值就是上次返回的 Etag 的值。
  • 服务接收到请求后会根据这个值来和资源当前的 Etag 的值进行比较,以此来判断资源是否发生改变,是否需要返回资源。通过这种方式,比 Last-Modified 的方式更加精确。
  • 当 Last-Modified 和 Etag 属性同时出现的时候,Etag 的优先级更高。使用协商缓存的时候,服务器需要考虑负载平衡的问题,因此多个服务器上资源的 Last-Modified 应该保持一致,因为每个服务器上 Etag 的值都不一样,因此在考虑负载平衡时,最好不要设置 Etag 属性。 image.png

缓存综述 手画

image.png

刷新操作方式,对缓存的影响

  • 正常操作:地址栏输入url,跳转连接,前进后退等;强制缓存有效,协商缓存有效
  • 手动刷新:F5,点击刷新按钮,右击菜单刷新;强制缓存失效,协商缓存有效
  • 强制刷新:ctrl + F5;强制缓存失效,协商缓存失效

获取url地址

//获取当前窗口的Url
var url = window.location.href;
//结果:http://localhost:61768/Home/Index?id=2&age=18

//获取当前窗口的主机名
var host = window.location.host;
//结果:localhost:61768

//获取当前窗口的端口
var port = window.location.port;
//结果:61768

//获取当前窗口的路径
var pathname = window.location.pathname;
//结果:/Home/Index

//获取当前文档的Url
var URL = document.URL;
//结果:http://localhost:61768/Home/Index?id=2&age=18

//获取参数
var search = window.location.search;
//结果:?id=2&age=18

HTTP协议

HTTP状态码

HTTP状态码分类

  • 1xx 服务器收到请求
  • 2xx 请求成功,如200
  • 3xx 重定向,如302
  • 4xx 客户端错误,如404
  • 5xx 服务端错误,如500

常见状态码

  • 200 成功
  • 301 永久重定向,配合location(新地址),浏览器自动处理,
  • 302 临时重定向(配合location, 浏览器自动处理)
  • 304 资源未被修改
  • 404 资源未找到
  • 403 没有权限
  • 500 服务器错误
  • 504 网关超时

自定义header

参考 image.png

get,post区别

Post 和 Get 是 HTTP 请求的两种方法,其区别如下:

  • 是否缓存:因为两者应用场景不同,浏览器一般会对 Get 请求缓存,但很少对 Post 请求缓存。
  • 发送的报文格式:Get 请求的报文中实体部分为空,Post 请求的报文中实体部分一般为向服务器发送的数据。
  • 安全性:Get 请求可以将请求的参数放入 url 中向服务器发送,这样的做法相对于 Post 请求来说是不太安全的,因为请求的 url 会被保留在历史记录中。
  • 请求长度:浏览器由于对 url 长度的限制,所以会影响 get 请求发送数据时的长度。这个限制是浏览器规定的,并不是 RFC 规定的。
  • 参数类型:GET只接受ASCII字符,而POST没有限制。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
  • GET参数通过URL传递,POST放在Request body中。

POST和PUT请求的区别

  • PUT请求是向服务器端发送数据,从而修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次PUT操作,其结果并没有不同。(可以理解为时更新数据
  • POST请求是向服务器端发送数据,该请求会改变数据的种类等资源,它会创建新的内容。(可以理解为是创建数据

常见的HTTP请求头和响应头

Request Headers 常见的请求头

  • Accept 浏览器可接收的数据格式
  • Accept-Encoding 浏览器可接收的压缩算法,如gzip
  • Accept-Languange 浏览器可接收的语言,如zh-CN
  • Connection: keep-alive 一次TCP连接重复使用
  • cookie 浏览器自带cookie并发送
  • Host 请求的域名(请求地址)
  • User-Agent(简称UA)浏览器信息
  • Content-type 发送数据的格式,如application/json

Response Headers 常见的响应头

  • Content-type 返回数据的格式,如application/json
  • Content-length 返回数据的大小,多少字节
  • Content-Encoding 返回数据的压缩算法,如gzip
  • Cache-Control:控制HTTP缓存

常见的 Content-Type 属性值有以下四种:

(1)application/x-www-form-urlencoded:浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。该种方式提交的数据放在 body 里面,数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL转码。

(2)multipart/form-data:该种方式也是一个常见的 POST 提交方式,通常表单上传文件时使用该种方式。

(3)application/json:服务器消息主体是序列化后的 JSON 字符串。

(4)text/xml:该种方式主要用来提交 XML 格式的数据。

HTTP 1.0 和 HTTP 1.1 之间有哪些区别?

  • 连接方面,http1.0 默认使用非持久连接,而 http1.1 默认使用持久连接,通过使用持久连接使得多个 http 请求复用同一个TCP 连接,以此来减少使用非持久连接时每次都需要重新建立TCP连接的时间。
  • 资源请求方面,在 http1.0 中,存在一些浪费带宽的现象,比如客户端只是需要某个对象的一部分,而服务器却将整个对象返回,并且不支持断点续传的功能,http1.1 在请求头中引入了 range 头域,它允许只请求资源的某一部分,并且返回的状态码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  • 缓存方面,在 http1.0 中主要使用 强缓存Expires,协商缓存Last-Modified(最后修改时间)来做为缓存判断的标准,http1.1 则引入了更多的缓存控制策略,比如 强缓存Cache-Control, 协商缓存Etag等更多可供选择的缓存头来控制缓存策略。
  • http1.1 中新增了 host 字段,用来指定服务器的域名。在http1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址。因此有了 host 字段,这样就可以将请求发送到同一台服务器上的不同网站。
  • http1.1 相对于 http1.0 还新增了很多请求方法,如 PUT、HEAD、OPTIONS 等。 相关资料
    持久连接和非持久连接
    新增请求方法

HTTP 1.1 和 HTTP 2.0 的区别

  • 二进制协议: HTTP/2.0 是一个二进制协议。在 HTTP/1.1 中,报文的头信息必须是文本(ASCII 编码),数据体可以是文本,也可以是二进制。HTTP/2.0 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧",可以分为头信息帧和数据帧。 帧的概念是它实现多路复用的基础。
  • 多路复用: HTTP/2.0 实现了多路复用,它仍然复用 TCP 连接,但是在一个连接里,客户端和服务器都可以同时发送多个请求或回应,而且不用按照顺序一一发送,这样就避免了"队头堵塞"的问题。
  • 数据流: HTTP/2.0 使用了数据流的概念,因为 HTTP/2.0 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的请求。因此,必须要对数据包做标记,指出它属于哪个请求。HTTP/2.0 将每个请求或回应的所有数据包,称为一个数据流。每个数据流都有一个独一无二的编号。当数据包发送时,都必须标记数据流 ID ,用来区分它属于哪个数据流。
  • 头信息压缩: HTTP/2.0 实现了头信息压缩,由于 HTTP 1.1 协议不带状态,每次请求都必须附上所有信息。这样就会造成,请求的很多字段都是重复的,比如 Cookie 和 User Agent ,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。HTTP/2.0 对这一点做了优化,引入了头信息压缩机制。一方面,头信息使用 gzip 或 compress 压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段,只发送索引号,这样就能提高速度。
  • 服务器推送: HTTP/2.0 允许服务器未经客户端请求,主动向客户端推送相关资源,这叫做服务器推送。通过使用服务器推送功能提前给客户端推送必要的资源,这样就可以相对的提高网页的加载速度。这里需要注意的是 http2.0 下服务器主动推送的是静态资源,和 WebSocket 以及使用 SSE 等方式向客户端发送即时数据的推送是不同的。

【1】队头堵塞:

队头阻塞是由 HTTP 基本的 “请求-应答” 模型所导致的。HTTP 规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列。队列里的请求是没有优先级的,只有入队的先后顺序,排在最前面的请求会被最优先处理。如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也得跟着一起等待,承担了不属于自己的时间成本,造成了队头堵塞的现象。

知识点
user-Agent: User-Agent是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA。用较为普通的一点来说,是一种向访问网站提供你所使用的浏览器类型、操作系统及版本、CPU 类型、浏览器渲染引擎、浏览器语言、浏览器插件等信息的标识。
头信息压缩
服务器推送
多路复用
数据包 串行并行的区别

HTTP和HTTPS协议的区别

  • HTTPS协议需要CA证书,费用较高;而HTTP协议不需要;
  • HTTP协议是超文本传输协议,信息是明文传输的,HTTPS则是具有安全性的SSL加密传输协议;
  • 使用不同的连接方式,端口也不同,HTTP协议默认端口是80,HTTPS协议默认端口是443;
  • HTTP协议连接很简单,是无状态的;HTTPS协议是由SSL和HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP更加安全。 https参考

当在浏览器中输入 Google.com 并且按下回车之后发生了什么?

  • 解析url
  • 缓存判断
  • DNS解析
  • TCP三次握手建立连接
  • 返回数据
  • 页面渲染
  • TCP四次挥手释放连接

(1)解析URL:首先会对 URL 进行解析,分析所需要使用的传输协议和请求的资源的路径。如果输入的 URL 中的协议或者主机名不合法,将会把地址栏中输入的内容传递给搜索引擎。如果没有问题,浏览器会检查 URL 中是否出现了非法字符,如果存在非法字符,则对非法字符进行转义后再进行下一过程。

(2)缓存判断:浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向服务器发起新的请求。

(3)DNS解析:下一步首先需要获取的是输入的 URL 中的域名的 IP 地址,首先会判断本地是否有该域名的 IP 地址的缓存,如果有则使用,如果没有则向本地 DNS 服务器发起请求。本地 DNS 服务器也会先检查是否存在缓存,如果没有就会先向根域名服务器发起请求,获得负责的顶级域名服务器的地址后,再向顶级域名服务器请求,然后获得负责的权威域名服务器的地址后,再向权威域名服务器发起请求,最终获得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给请求的用户。用户向本地 DNS 服务器发起请求属于递归请求,本地 DNS 服务器向各级域名服务器发起请求属于迭代请求。

(5)TCP三次握手:下面是 TCP 建立连接的三次握手的过程,首先客户端向服务器发送一个 SYN 连接请求报文段和一个随机序号,服务端接收到请求后向服务器端发送一个 SYN ACK报文段,确认连接请求,并且也向客户端发送一个随机序号。客户端接收服务器的确认应答后,进入连接建立的状态,同时向服务器也发送一个ACK 确认报文段,服务器端接收到确认后,也进入连接建立状态,此时双方的连接就建立起来了。

(6)HTTPS握手:如果使用的是 HTTPS 协议,在通信前还存在 TLS 的一个四次握手的过程。首先由客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法。服务器端收到后,确认加密的方法,也向客户端发送一个随机数和自己的数字证书。客户端收到后,首先检查数字证书是否有效,如果有效,则再生成一个随机数,并使用证书中的公钥对随机数加密,然后发送给服务器端,并且还会提供一个前面所有内容的 hash 值供服务器端检验。服务器端接收后,使用自己的私钥对数据解密,同时向客户端发送一个前面所有内容的 hash 值供客户端检验。这个时候双方都有了三个随机数,按照之前所约定的加密方法,使用这三个随机数生成一把秘钥,以后双方通信前,就使用这个秘钥对数据进行加密后再传输。

(7)返回数据:当页面请求发送到服务器端后,服务器端会返回一个 html 文件作为响应,浏览器接收到响应后,开始对 html 文件进行解析,开始页面的渲染过程。

(8)页面渲染:浏览器首先会根据 html 文件构建 DOM 树,根据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判端是否含有 defer 或者 async 属性,要不然 script 的加载和执行会造成页面的渲染的阻塞。当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树。渲染树构建好后,会根据渲染树来进行布局。布局完成后,最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。

(9)TCP四次挥手:最后一步是 TCP 断开连接的四次挥手过程。若客户端认为数据发送完成,则它需要向服务端发送连接释放请求。服务端收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明客户端到服务端的连接已经释放,不再接收客户端发的数据了。但是因为 TCP 连接是双向的,所以服务端仍旧可以发送数据给客户端。服务端如果此时还有没发完的数据会继续发送,完毕后会向客户端发送连接释放请求,然后服务端便进入 LAST-ACK 状态。客户端收到释放请求后,向服务端发送确认应答,此时客户端进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有服务端的重发请求的话,就进入 CLOSED 状态。当服务端收到确认应答后,也便进入 CLOSED 状态。

HTTP状态码304是多好还是少好

服务器为了提高网站访问速度,对之前访问的部分页面指定缓存机制,当客户端在此对这些页面进行请求,服务器会根据缓存内容判断页面与之前是否相同,若相同便直接返回304,此时客户端调用缓存内容,不必进行二次下载。

状态码304不应该认为是一种错误,而是对客户端有缓存情况下服务端的一种响应。

搜索引擎蜘蛛会更加青睐内容源更新频繁的网站。通过特定时间内对网站抓取返回的状态码来调节对该网站的抓取频次。若网站在一定时间内一直处于304的状态,那么蜘蛛可能会降低对网站的抓取次数。相反,若网站变化的频率非常之快,每次抓取都能获取新内容,那么日积月累,的回访率也会提高。

产生较多304状态码的原因:

  • 页面更新周期长或不更新
  • 纯静态页面或强制生成静态html

304状态码出现过多会造成以下问题:

  • 网站快照停止;
  • 收录减少;
  • 权重下降。

常见的HTTP请求方法

传统methods

  • get获取服务器数据
  • post像服务器提交数据

methods - 1

  • get 获取数据
  • post 新建数据
  • patch/put 更新数据
  • delete 删除数据

Restful API

  • 一种新的API设计方法(早已推广使用)
  • 传统API设计:把每个url当做一个功能
  • Restful API设计:把每个url当做一个唯一的资源,不使用url参数 参考 为什么不用普通的接口方式,比如你要从你的网站上面得到一个城市的天气,以前有可能你得这么设计

https://xxx/weather?city=深圳

你这样就得传两个参数给后台,这样看起来就很臃肿。

用RESTful方式设计接口你可能会这么设计

https://xxx/weathers/深圳

这样只需要传一个参数给后台就可以了,这样看起来很简洁,而且我们的URI中使用的是名词,而不是动词。通过HTTP动词来实现资源的跳转。具体实现方式下面说。 以上就是我们为什么要使用RESTful API结构的原因。

post 请求 /api/bolg
patch 请求 /api/blog/100
get 请求 /api/blog/100

OPTIONS请求方法及使用场景

OPTIONS是除了GET和POST之外的其中一种 HTTP请求方法。

OPTIONS方法是用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。该请求方法的响应不能缓存。

OPTIONS请求方法的主要用途有两个:

  • 获取服务器支持的所有HTTP请求方法;
  • 用来检查访问权限。例如:在进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限。

HTTPS协议

参考 视频参考

1. 什么是HTTPS协议?

超文本传输安全协议(Hypertext Transfer Protocol Secure,简称:HTTPS)是一种通过计算机网络进行安全通信的传输协议。HTTPS基于HTTP进行通信,利用SSL/TLS来加密数据包。HTTPS的主要目的是提供对网站服务器的身份认证,保护数据交换的隐私与完整性。

image

HTTPS协议比HTTP协议有那些优势
HTTP协议采用明文传输信息,存在信息窃听信息篡改信息劫持的风险,而HTTPS协议则具有身份验证信息加密完整性校验的功能,可以避免此类问题的发生。

安全层的主要职责就是对发起的HTTP请求的数据进行加密操作 和 对接收到的HTTP的内容进行解密操作

2. TLS/SSL的工作原理

TLS/SSL全称安全传输层协议(Transport Layer Security), 是介于TCP和HTTP之间的一层安全协议,不影响原有的TCP协议和HTTP协议,所以使用HTTPS基本上不需要对HTTP页面进行太多的改造。

TLS/SSL的功能实现主要依赖三类基本算法:散列函数hash对称加密非对称加密。这三类算法的作用如下:

  • 基于散列函数验证信息的完整性
  • 对称加密算法采用协商的秘钥对数据加密
  • 非对称加密实现身份认证和秘钥协商

image

(1)散列函数hash

常见的散列函数有MD5、SHA1、SHA256。该函数的特点是单向不可逆,对输入数据非常敏感,输出的长度固定,任何数据的修改都会改变散列函数的结果,可以用于防止信息篡改并验证数据的完整性。

但是在信息传输过程中,散列函数自己不能实现信息防篡改,由于传输是明文传输,中间人可以修改信息后重新计算信息的摘要,所以需要对传输的信息和信息摘要进行加密。

长度固定 MD5 128bit
位、字节的区别

(2)对称加密

对称加密是指双方使用同一个秘钥对数据进行加密和解密。常见的对称加密算法有AES-CBC、AES-GCM、DES、3DES等。但是对称加密存在一个问题,就是如何保证秘钥传输的安全性,因为秘钥还是会通过网络传输的,一旦秘钥被其他人获取到,那么整个加密过程就毫无作用。这就需要要用到非对称加密的方法。

特点 对称加密的优势就是信息传输使用一对一,需要共享相同的密码,密码的安全是保证信息安全的基础,服务器和N个客户端通信,需要维持N个密码记录且不能修改密码。

(3)非对称加密

常见的非对称加密算法有RSA、ECC、DH等,非对称加密是指我们拥有两个秘钥,一个是公钥,一个是私钥。公钥是公开的,私钥是保密的。用公钥加密的数据,只有对应的私钥才能解密。我们可以将公钥公布出去,任何想和我们通信的客户,都可以使用我们提供的公钥对数据进行加密,当接收到数据之后我们在用私钥进行解密,保证数据的安全性。但是非对称加密有一个缺点就是加密的过程很慢,如果每次通信都使用非对称加密的话,反而会造成等待时间过长的问题。

特点 非对称加密的特点就是信息一对多,服务器只需要维持一个私钥就可以和多个客户端进行通信,但服务器发出的信息能够被所有的客户端解密,且该算法的计算复杂,加密的速度慢。

综合上述算法特点,TLS/SSL的工作方式就是客户端使用非对称加密与服务器进行通信,实现身份的验证并协商对称加密使用的秘钥。对称加密算法采用协商秘钥对信息以及信息摘要进行加密通信,不同节点之间采用的对称秘钥不同,从而保证信息只能通信双方获取。

对称,非对称加密结合使用

3. 数字证书是什么?

数字证书是指在互联网通讯中标志通讯各方身份信息的一个数字认证,人们可以在网上用它来识别对方的身份。

背景:因为通过非对称加密也不一定是安全的,没有办法确定得到的公钥就一定是安全的公钥。可能存在一个中间人,截取了对方发给我们的公钥,然后将他自己的公钥发送给我们,当我们使用他的公钥加密后发送的信息,就可以被他用自己的私钥解密。然后他伪装成我们以同样的方法向对方发送信息,这样我们的信息就被窃取了,然而自己还不知道。为了解决这样的问题,可以使用数字证书。

数字证书的过程如下:首先使用一种 Hash(哈希) 算法来对公钥和其他信息进行加密,生成一个信息摘要,然后让有公信力的认证中心(简称 CA )用它的私钥对消息摘要加密,生成数字签名。最后将原始的信息和签名合在一起,称为数字证书。当接收方收到数字证书的时候,先根据原始信息使用同样的 Hash(哈希) 算法生成一个摘要,然后使用公证处的公钥来对数字证书中的数字签名进行解密,最后将解密的摘要和生成的摘要进行对比,就能发现得到的信息是否被更改了。

这个方法最要的是认证中心的可靠性,一般浏览器里会内置一些顶层的认证中心的证书,相当于我们自动信任了他们,只有这样才能保证数据的安全。 image

DNS协议

DNS 协议是什么

概念: DNS 是域名系统 (Domain Name System) 的缩写,提供的是一种主机名到 IP 地址的转换服务,它是一个由分层的 DNS 服务器组成的分布式数据库,是定义了主机如何查询这个分布式数据库的方式的应用层协议。能够使人更方便的访问互联网,而不用去记住IP地址。

DNS同时使用TCP和UDP协议?

DNS占用53号端口,同时使用TCP和UDP协议。

(1)在区域传输的时候使用TCP协议

  • 辅域名服务器会定时(一般3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,会执行一次区域传送,进行数据同步。区域传送使用TCP而不是UDP,因为数据同步传送的数据量比一个请求应答的数据量要多得多。
  • TCP是一种可靠连接,保证了数据的准确性。

(2)在域名解析的时候使用UDP协议

  • 客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过三次握手,这样DNS服务器负载更低,响应更快。理论上说,客户端也可以指定向DNS服务器查询时用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。

DNS完整的查询过程

DNS服务器解析域名的过程:

  • 首先浏览器会在缓存中查找对应的IP地址,如果查找到直接返回,如果没有
  • 将请求发送给本地DNS服务器,在本地DNS服务器缓存中查询,如果查找到,就直接将查找结果返回,如果没有
  • 本地DNS服务器向根域名服务器发送请求,根域名服务器会返回对应查询域的顶级域名服务器地址
  • 本地DNS服务器向顶级域名服务器发送请求,接受请求的服务器查询自己的缓存,如果有记录,就返回查询结果,如果没有就返回相关的下一级的权威域名服务器的地址
  • 本地DNS服务器向权威域名服务器发送请求,域名服务器返回对应的结果
  • 本地DNS服务器将返回结果保存在缓存中,便于下次使用
  • 本地DNS服务器将返回结果返回给浏览器

比如要查询 www.baidu.com 的 IP 地址,首先会在浏览器的缓存中查找是否有该域名的缓存,如果不存在就将请求发送到本地的 DNS 服务器中,本地DNS服务器会判断是否存在该域名的缓存,如果不存在,则向根域名服务器发送一个请求,根域名服务器返回负责 .com 的顶级域名服务器的 IP 地址的列表。然后本地 DNS 服务器再向其中一个负责 .com 的顶级域名服务器发送一个请求,负责 .com 的顶级域名服务器返回负责 .baidu 的权威域名服务器的 IP 地址列表。然后本地 DNS 服务器再向其中一个权威域名服务器发送一个请求,最后权威域名服务器返回一个对应的主机名的 IP 地址列表。

知识点
根域名

迭代查询与递归查询

实际上,DNS解析是一个包含迭代查询和递归查询的过程。

  • 递归查询指的是查询请求发出后,域名服务器代为向下一级域名服务器发出请求,最后向用户返回查询的最终结果。使用递归 查询,用户只需要发出一次查询请求。
  • 迭代查询指的是查询请求后,域名服务器返回单次查询的结果。下一级的查询由用户自己请求。使用迭代查询,用户需要发出 多次的查询请求。

一般我们向本地 DNS 服务器发送请求的方式就是递归查询,因为我们只需要发出一次请求,然后本地 DNS 服务器返回给我 们最终的请求结果。而本地 DNS 服务器向其他域名服务器请求的过程是迭代查询的过程,因为每一次域名服务器只返回单次 查询的结果,下一级的查询由本地 DNS 服务器自己进行。

DNS 记录和报文

DNS 服务器中以资源记录的形式存储信息,每一个 DNS 响应报文一般包含多条资源记录。一条资源记录的具体的格式为

(Name,Value,Type,TTL)

其中 TTL 是资源记录的生存时间,它定义了资源记录能够被其他的 DNS 服务器缓存多长时间。

常用的一共有四种 Type 的值,分别是 A、NS、CNAME 和 MX ,不同 Type 的值,对应资源记录代表的意义不同:

  • 如果 Type = A,则 Name 是主机名,Value 是主机名对应的 IP 地址。因此一条记录为 A 的资源记录,提供了标 准的主机名到 IP 地址的映射。
  • 如果 Type = NS,则 Name 是个域名,Value 是负责该域名的 DNS 服务器的主机名。这个记录主要用于 DNS 链式 查询时,返回下一级需要查询的 DNS 服务器的信息。
  • 如果 Type = CNAME,则 Name 为别名,Value 为该主机的规范主机名。该条记录用于向查询的主机返回一个主机名 对应的规范主机名,从而告诉查询主机去查询这个主机名的 IP 地址。主机别名主要是为了通过给一些复杂的主机名提供 一个便于记忆的简单的别名。
  • 如果 Type = MX,则 Name 为一个邮件服务器的别名,Value 为邮件服务器的规范主机名。它的作用和 CNAME 是一 样的,都是为了解决规范主机名不利于记忆的缺点。

TCP与UDP

TCP 和 UDP都是传输层协议,他们都属于TCP/IP协议族:

UDP

UDP的全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在传输层,处于IP协议的上一层。

它有以下优点:
1)UDP无须建立连接。因此UDP不会引入建立连接的时延。试想如果DNS运行在TCP而不是UDP上,那么DNS的速度会慢很多。HTTP使用TCP而非UDP,是因为对于基于文本数据的网页来说,可靠性是非常重要的。
2)无连接状态。TCP需要在端系统中维护连接状态。此连接状态包括接收和发送缓存、拥塞机制参数和序号与确认号8

TCP

TCP的全称是传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,它主要实现传输过程中的可靠,有序,无丢失和不重复的功能。

主要特点有
1)TCP是面向连接的传输层协议
2)每条TCP连接只能有两个端点,必须是点对点的(一对一)。
3)TCP提供可靠的交付服务,保证传送的数据无差错、不丢失、不重复且有序。
4)TCP提供全双工通信,允许通信双方的应用进程在任何时候都能发送数据,为此TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。
5)TCP是面向字节流的,虽然应用程序和TCP的交互是一次一个数据块,但是TCP把应用程序交下来的数据仅视为一连串的无结构的字节流

三次握手

image

连接建立前,服务器进程处于LISTEN(收听)状态,等待客户端的连接请求。
第一次握手:客户端向服务器发送连接请求报文段。报文段的首部中的同步位SYN=1,初始序号seq=x。这时,客户端进程进入SYN-SENT(同步已发送)状态。
第二次握手:服务器收到连接请求报文段后,如果同意建立连接,则向客户端发回确认,并为该TCP连接分配缓存和变量。在确认报文段中,同步位SYN=1,确认位ACK=1,确认号ack=x+1,同时确认报文段也有自己的初始序号seq=y。这时,服务器进程进入SYN-RCVD(同步收到)状态。
第三次握手:当客户端收到确认报文段后,还要向服务器发回确认,并为该TCP连接分配缓存和变量。确认报文段的SYN=0,ACK=1,ack=y+1,seq=x+1并且该报文段可以携带数据。这时客户端进入ESTABLISHED(已建立连接)状态。

知识点

  • 确认位ACK。仅当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。
  • 同步位SYN。同步SYN = 1表示这是一个连接请求或连接接受报文。当SYN=1,ACK=0时,表明这是一个连接请求报文,对方若同意建立连接,则应在响应报文中使用SYN=1,ACK=1。

SYN洪范攻击

SYN洪泛攻击利用TCP协议的特性,就是三次握手。攻击者向目标服务器发送连接请求报文段, 当服务器返回A确认报文后,攻击者就不对其进行再确认,那么这个TCP连接就处于挂起状态,也就是所谓的半连接状态,服务器收不到再确认的话,还会重复发送确认报文给攻击者。这样更加会浪费服务器的资源。攻击者可以对服务器发送大量的这种TCP连接,由于每一个都没法完成三次握手,所以在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务,解决办法可以设置SYN.cookie。

为什么TCP连接的时候是3次?两次是否可以?

不可以,主要从以下两方面考虑(假设客户端是首先发起连接请求) :

  1. 假设建立TCP连接仅需要两次握手,那么如果第二次握手时,服务端返回给客户端的确认报文丢失了,客户端这边认为服务端没有和他建立连接,而服务端却以为已经和客户端建立了连接,并且可能向服务端已经开始向客户端发送数据,但客户端并不会接收这些数据,浪费了资源。如果是三次握手,不会出现双方连接还未完全建立成功就开始发送数据的情况。

  2. 如果服务端接收到了一个早已失效的来自客户端的连接请求报文,会向客户端发送确认报文同意建立TCP连接。但因为客户端并不需要向服务端发送数据,所以此次TCP连接没有意义并且浪费了资源。

四次挥手

image

第一次挥手:客户端向服务器发送的数据完成后,向服务器发起连接释放报文,报文包含终止位FIN=1,序列号seq=u(它等于前面已经传送过的数据的最后一个字节的序号加1)。此时客户端进入FIN-WAIT-1(终止等待1)状态只能接收数据,不能向服务端发送数据。
第二次挥手:当服务器收到连接释放报文段后向客户端发出确认,确认报文段ack=u+1,序号seq=v(等于它前面已经传送过的数据的最后一个字节的序号加1)。然后服务器进入CLOSE-WAIT(关闭等待)状态。此时,从客户端到服务器这个方向的连接就释放了,TCP连接处于半关闭状态。但服务器仍然可以发送数据,客户端还可以接收。
第三次挥手:如果服务器没有要向客户端发送的数据了,就向客户端发出连接释放报文。报文包含FIN=1,ACK=1,seq=w,ack=u+1。这时服务器进入LAST-ACK(最后确认)状态。
第四次挥手:客户端收到连接释放报文段后,必须发出确认。确认报文段包含ACK=1,ack=w+1,seq=u+1.此时TCP连接还未释放,必须经过时间等待计时器设置的时间2MSL(最长报文段寿命)后,客户端才进入CLOSED(连接关闭)状态

为什么TCP连接的时候是3次,关闭的时候却是4次?

因为需要确保通信双方都能通知对方释放连接,假设客服端发送完数据向服务端发送释放连接请求,当客服端并不知道,服务端是否已经发送完数据,所以此次断开的是客服端到服务端的单向连接,服务端返回给客户端确认报文后,服务端还能继续单向给客户端发送数据。当服务端发送完数据后还需要向客户端发送释放连接请求,客户端返回确认报文, TCP连接彻底关闭。所以断开TCP连接需要客户端和服务端分别通知对方并分别收到确认报文,一共需要四次。

为什么客户端发出第四次挥手的确认报文后要等2MSL的时间才能释放TCP连接?

MSL的意思是报文的最长寿命,可以从两方面考虑:
1.客户端发送第四次挥手中的报文后,再经过2MSL,可使本次TCP连接中的所有报文全部消失,不会出现在下一个TCP连接中。
2.考虑丢包问题,如果第四挥手发送的报文在传输过程中丢失了,那么服务端没收到确认ack报文就会重发第三次挥手的报文。如果客户端发送完第四次挥手的确认报文后直接关闭,而这次报文又恰好丢失,则会造成服务端无法正常关闭。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

如果TCP连接已经建立,在通信过程中,客户端突然故障,那么服务端不会一直等下去,过一段时间就 关闭连接了。具体原理是TCP有一个保活机制,主要用在服务器端,用于检测已建立TCP链接的客户端的 状态,防止因客户端崩溃或者客户端网络不可达,而服务器端直保持该TCP链接,占用服务器端的大 量资源(因为Linux系统中可以创建的总TCP链接数是有限制的)。
保活机制原理:设置TCP保活机制的保活时间keepldle,即在TCP链接超过该时间没有任何数据交互时, 发送保活探测报文;设置保活探测报文的发送时间间隔keepInterval;设置保活探测报文的总发送次数 keepCount。如果在keepCount次的保活探测报文均没有收到客户端的回应,则服务器端即关闭与客户 端的TCP链接。

TCP和UDP的区别

TCP是面向连接的传输层控制协议,传送数据之前必须建立连接,结束后要释放连接,不提供广播域或多播服务。由于TCP要提供可靠的面向连接的传输服务,因此不可避免增加了许多开销比如:确认、流量控制、计数器及连接管理等。它的特点是可靠,面向连接,时延大,适用于大文件。 UDP是无连接的用户数据报协议,传送数据之前不需要建立连接,收到UDP报文后也不需要给出任何确认。它的特点是不可靠,无连接,时延小,适用于小文件。