Http协议及TCP/IP

1.   了解部分有意义的头部信息

头部信息  
Catch-Control:max-age=100 静态资源缓存100s
Content-Type,Content-Encoding 等 用来约束数据类型
Cookie    保持会话信息
CORS  实现跨域并保持安全性限制

2.    页面如何到达浏览器并展现给用户

Redirect(跳转)--> App catch(应用缓存)-->DNS(DNS查找)-->TCP (创建TCP链接)-->Request(发送请求)

-->Response(接受响应)

1. redirect : 对于浏览器已经记录过的301请求,直接跳转,属于纯客户端的行为。

2. cache: 根据资源是否有设置cache control ,然后判断缓存。如果超时则要重新请求缓存。

3. DNS查询:当通过浏览器请求一个web页面,浏览器会创建一个线程去处理这个请求,随后开始远程dns查找,远程dns服务器会将输入的URL对应的IP地址返回给浏览器。(DNS域名系统)

4. TCP连接: 三次握手 (HTTP请求是在TCP连接上发送的,一个TCP连接可以发送多个HTTP请求)

5. 发送请求: 数据经过代理服务器或代理服务器缓存直接读取。浏览器通过连接发送一个HTTP GET请求到Web服务端。

6. 接受响应。Web服务端找到请求的资源,然后在HTTP响应中将其返回,状态200表示响应正常。

常用状态码:

  • 200: 服务端成功响应
  • 301: 永久重定向
  • 302: 临时重定向
  • 403: 请求被拒绝
  • 404: 服务端找不到请求的资源
  • 500: 处理请求时出错
  • 503: 服务不可用
  • 504: 网关超时

   最后,浏览器收到页面HTML,就开始解析并渲染页面内容

3.   网络协议分层

经典的五层网路模型:

 物理层:定义物理设备如何传输数据(电脑硬件,网卡端口,光缆...)。

数据链路层: 在通信的实体间建立数据链路连接。

网络层:为数据在节点之间传输创建逻辑链路。

传输层: 向用户提供可靠的端对端(end-to-end)服务。更多情况下实用TCP/IP协议传输数据。

              定义如何传输数据,传输数据的方式。

应用层:为应用软件提供了很多的服务。构建于TCP协议之上。

4.   HTTP/1.1

pipeline: 可以通过声明,在同一个连接里发送多个请求

增加host:可以在同一台物理服务器跑多个不同的web服务

HTTP 2 : 所有数据以二进制传输,同一个连接里发送多个请求不再需要按照顺序,头信息压缩以及推送等提高效率的功能。

推送功能(请求html的同时,可以将html中需要引用到的JavaScript文件和css文件推送到客户端,实现html和css js文件的发送顺序是闭型的,提高整体的传输效率)

5.  三次握手

为了防止服务端开启无用的连接。(网络服务器延迟等)

浏览器通过与远程web服务端的三次握手来建立一个TCP/IP请求。这个握手由浏览器与远程服务端之间的SYN(标志位),SYN-ACK,ACK消息组成。(SYN:同步序列编号)

                                                图1  TCP 三次握手

6.   统一资源定位器  Uniform Resource Locators

scheme://host.domain:port/path/filename

说明:

  • scheme - 定义因特网服务的类型。最常见的类型是 http
    • host - 定义域主机(http 的默认主机是 www)
    • domain - 定义因特网域名,比如 runoob.com
    • :port - 定义主机上的端口号(http 的默认端口号是 80)
    • path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
    • filename - 定义文档/资源的名称

7.   创建一个最简单的web服务

server.js文件下创建如下内容: 

const http = require('http')

http.createServer((request, response) => {
  console.log('request', request.url)

  response.end('123')
}).listen(8888)

console.log('server listening on 8888')

启动: node server.js

浏览器打开:localhost:8888, 查看内容

利用curl命令查看http报文信息

$ curl -v www.baidu.com

能得到报文头和header的内容:

 * Rebuilt URL to: www.baidu.com/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*                                                                                                                   Trying 14.215.177.39...
* TCP_NODELAY set
* Connected to www.baidu.com (14.215.177.39) port 80 (#0)
> GET / HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/7.57.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: Keep-Alive
< Content-Length: 2381
< Content-Type: text/html
< Date: Fri, 17 Aug 2018 05:07:47 GMT
< Etag: "588604cf-94d"
< Last-Modified: Mon, 23 Jan 2017 13:27:43 GMT
< Pragma: no-cache
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<
{ [1048 bytes data]
100  2381  100  2381    0     0   2381      0  0:00:01 --:--:--  0:00:01 74406

8.   跨域请求

新建server.js: 创建请求

//在8888端口中请求了一个8887端口的内容

const http = require('http')
const fs = require('fs')

http.createServer((request, response) => {  //创建请求
  console.log('request', request.url)

  const html = fs.readFileSync('test.html', 'utf8');  //同步读取html内容
  response.writeHead(200, {
    'Content-Type': 'text/html'
  })

  response.end(html)  //响应内容
}).listen(8888)

console.log('server listening on 8888')

server2.js

const http = require('http')

http.createServer((request, response) => {
  console.log('request', request.url)

  // 允许跨域请求  写返回的状态
  response.writeHead(200, {
    'Access-Control-Allow-Origin': '*'
  })

  response.end('123')
}).listen(8887)

console.log('server listening on 8887')

test.html 中向8887端口发送请求:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>test</title>
</head>
<body>
  <script>
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'http://127.0.0.1:8887/')
    xhr.send()
  </script>
</body>
</html>

发送预请求:(跨域限制:保证服务端的安全)

预请求  
允许的方法 GRT、POST、HEAD
允许Content-Type

text/plain、multipart/formdata、

application/x-www-form-urlencoded

通过options请求获得服务器的认可

server.js:

//相当于在8888端口中请求了一个8887端口的内容

const http = require('http')
const fs = require('fs')

http.createServer((request, response) => {  //创建请求
  console.log('request', request.url)

  const html = fs.readFileSync('test.html', 'utf8');  //同步读取html内容
    response.writeHead(200, {
      'Content-Type': 'text/html'
    })
  response.end(html)  //响应内容

}).listen(8888)

console.log('server listening on 8888')

server2.js:

const http = require('http')

http.createServer((request, response) => {
  console.log('request', request.url)

  // 允许跨域请求  写返回的状态
  response.writeHead(200, {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Headers': 'X-Test-Cors',  //允许自定义的头
    'Access-Control-Allow-Methods': 'PUT, POST, GET',
    'Access-Control-Max-Age': '1000'
  })

  response.end('123')
}).listen(8887)

console.log('server listening on 8887')

Access-Control-Max-Age 这个响应首部表示 preflight request  (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久。

缓存Cache-Control: (哈希值用于刷新浏览器缓存)

可缓存性  
public 任何地方都可以对返回的内容缓存
private 只有发起请求的地方可以
no-cache 通过服务器端验证后才能使用本地缓存
到期  
max-age=<seconds>

缓存还有多过期。      可以将max-age设置为0,

从而让每次访问时缓存都进行刷新。

max-stale=<seconds> 可以使用多久的过期缓存
重新验证  
must-revalidata 如果要提供过期的数据给客户端,则必须向服务器验证数据的新鲜度

缓存验证:

缓存验证  
Last-Modified '123'  标记此文件在服务器端最后被修改的时间
Etag '777'   用于标示URL对象是否改变

no-store: 忽略缓存

9. Cookie和Session

Cookie:1. 通过Set-Cookie设置   2. 下次请求会自动带上  3.键值对,可以设置多个

属性: 

Cookie属性  
max-age和expires 设置过期时间
Secure 只在https的时候发送
HttpOnly 无法通过document.cookie访问,保证用户安全

服务端server.js:

const http = require('http')
const fs = require('fs')

http.createServer((request, response) => {  //创建请求
  console.log('request', request.url)

  if (request.url === '/') {
    const html = fs.readFileSync('test.html', 'utf8');  //同步读取html内容
    response.writeHead(200, {
      'Content-Type': 'text/html',
      'Set-Cookie': ['abc=123; max-age=2','id=456'], //可以以数组方式传递多个cookie 前面一个字段的有效时间为两秒
      // 2s后abc=123这个数据就过期,request headers中就不会有这个信息出现
    })
    response.end(html)  //响应内容
  }

}).listen(8888)

console.log('server listening on 8888')

客户端test.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>test</title>
</head>
<body>
  <div>content</div>
  <script src="/script.js">
    console.log(document.cookie)
  </script>
</body>
</html>

10.  数据协商: 

      客户端请求时会声明希望拿到的数据格式和限制,服务端根据请求头返回不同的数据

客户端请求

Accept

声明想要的数据类型

[主类型]/[子类型] ,如text/html,image/jpg

Accept-Encoding

声明进行传输的编码方式

主要是数据压缩的算法,如gzip, deflate, br

Accept-Language

声明希望返回信息的语言

如zh-CN,zh;q=0.9(q表权重,0~1)

Usrer-Agent

声明浏览器和操作系统的相关信息
服务端返回

Content-Type

声明返回的数据格式,

如'X-Content-Type-Options':'nosniff',可阻止浏览器自行猜测返回数据类型而引发的安全问题。

Content-Encoding

声明返回的编码方式,即数据压缩

Content-Language

声明返回的语言

表单发送到服务器时的三种编码方式:

enctype(编码方式)
application/x-www-form-urlencoded 默认的编码方式。但是在用文本的传输和MP3等大型文件的时候,使用这种编码就显得 效率低下。 
multipart/form-data 指定传输数据为二进制类型,比如图片、mp3、文件
text/plain 纯文体的传输。空格转换为 “+” 加号,但不对特殊字符编码

将表单的enctype(编码方式)定义为"multipart/form-data":适用于上传文件的方式

  <form method="POST" enctype="multipart/form-data">
    <input type="text" name="name">
    <input type="password" name="psd">
    <input type="submit">
  </form>

提交表单之后:能够在浏览器请求头中得到如下信息:

Request Header:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryCoZcoYObU8Ubn5U2

boundary后的字符串用于分割表单中的每一个部分。

------WebKitFormBoundaryCoZcoYObU8Ubn5U2
Content-Disposition: form-data; name="name"

8月5
------WebKitFormBoundaryCoZcoYObU8Ubn5U2
Content-Disposition: form-data; name="psd"

sss
------WebKitFormBoundaryCoZcoYObU8Ubn5U2--

控制台中的connection ID 代表TCP连接的ID,可以用来区分是否用的同一个连接。

connection: close, //没有重复利用TCP连接,每次TCP请求发送完就关闭了

(HTTP请求是在TCP连接上发送的,一个TCP连接可以发送多个HTTP请求)

11.   Content Security Policy (内容安全策略)

1.  限制资源获取   2.   报告资源获取越权

CSP 大大增强了网页的安全性。

两种方法启动CSP:

1. 一种是通过 HTTP 头信息的Content-Security-Policy的字段

Content-Security-Policy: script-src 'self'; object-src 'none';

2. 通过网页的<meta>标签。

<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'">

( 脚本:只信任当前域名  <object>标签:不信任任何URL,即不加载任何资源)

只允许通过http,https方式加载src资源:

      'Content-Security-Policy': 'default-src http: https:'

只能根据本域名下的JavaScript内容进行加载:

      'Content-Security-Policy': 'default-src self'

猜你喜欢

转载自blog.csdn.net/weixin_41892205/article/details/81747490