在鸡年的最后一天完成了这篇文章表示愉悦的同时, 更要祝福大家狗年大吉吧....
下方是一根不正经的分割线...
重新学习前端知识, 自己整理总结了些内容... 所以想分享给大家在分享的同时, 也可以自己学习的更扎实... 如果有错误或者理解不正确的地方, 麻烦告知我会及时更正同时也非常欢迎大家一起讨论鞠躬 Github 地址: 项目地址 (不定期更新...
HTTP 协议
定义
HTTP( HyperText Transfer Protocol )超文本传输协议 , 是一种用于分布式协作式和超媒体信息系统的应用层协议设计 HTTP 最初的目的是为了提供一种发布和接收 html 页面的方法通过 HTTP 或者 HTTPS 协议请求的资源由统一资源标识符 (Uniform Resource Identifiers,URI) 来标识
TCP/IP & HTTP
HTTP 是如何建立连接的
首先我们要看下熟知的七层网络模型 (计算机网络中的七层模型毕竟是理想中的情况, 现实是很少有应用实现了七层模型, 一般都是整合其中两个或多个, 实现一个四层或者五层的模型) 和 TCP/IP 的四层网络模型 (TCP 处于传输层, IP 属于网络(际) 层 ps: 关于 TCP/IP 究竟是几层协议, 目前为止没有定论, 四层和五层都有, 这里不展开讨论 ), 如下图
网络模型
在这里我们研究的是 HTTP, 自然要知道它所处在哪个模型中, 答案是应用层
因为 HTTP 是基于 TCP/IP 开发的协议, 看过 HTTP 协议的同学肯定都知道, 有句话概述 HTTP 协议为无差错的协议, 按序传输, 未分段的数据流, 这其实说的就是 TCP 协议
当你在浏览器输入一个 URL 的时候, 其中发生了什么?
获取主机名
DNS 缓存 / 解析 获取服务器 IP + 端口 (浏览器缓存, 系统缓存, 路由器缓存, IPS 服务器缓存, 根域名服务器缓存, 顶级域名服务器缓存, 主域名服务器缓存)
连接到服务器 (这里其实是 TCP 连接)
通过 TCP 信道发送一个 HTTP 请求
服务器读取一个 HTTP 请求
服务器查找所需资源并通过 TCP 信道返回资源
关闭 TCP 连接
版本变迁
HTTP/0.9 已过时, 只接受 GET 一种请求方法, 没有在通讯中指定版本号, 且不支持请求头.
HTTP/1.0 第一个在通讯中指定版本号的 HTTP 协议版本
HTTP/1.1 继承了 HTTP1.0 简单的特点, 持久连接被默认建立, 并能很好地配合代理服务器工作还支持以管道方式在同时发送多个请求, 以便降低线路负载, 提高传输速度
HTTP/2.0 2015 年 5 月作为互联网标准正式发布
HTTP 客户端请求和服务端响应(目前主流的 HTTP1.1 和 HTTP2
请求组成
起始行(start line)
请求方法 + 请求 URI + 协议版本
报文首部(Header)
空行
报文主体
响应组成
起始行(start line)
协议版本 + 状态码 + 状态嘛的原因短语
报文首部(Header)
空行
报文主体
请求方法
GET 获取资源
HEAD 获得报文首部
POST -- 传输实体文本
PUT -- 传输文件
DELETE 删除文件
CONNECT 要求用隧道协议连接代理
OPTIONS 询问支持的方法
TRACE 追踪路径
首部文件 这一块图解 HTTP 的第六章有详细内容
通用首部
信息: Connection/Date/MIME-Version/Trailer/Update/Via
缓存: Cache-Control/Pragma
请求首部
信息: Client-IP/From/Host/Referer/UA-Color/UA-CPU/UA-Disp/UA-OS/UA-Pixels/User-Agent
Accept:Accept/Accept-Charset/Accept-Encoding/Accept-Language/TE
条件请求: Expect/If-Match/If-Modified-Since/If-None-Match/If-Range/If-Unmodified-Since/Range
安全请求: Authorization/Cookie/Cookie2
代理请求: Max-Forward/Proxy-Authorization/Proxy-Connection
响应首部
信息: Age/Public/Retry-After/Server/Title/Warning
协商: Accept-Ranges/Vary
安全响应: Proxy-Authorization/Set-Cookie/Set-Cookie2/WWW-Authenticate
实体首部
信息: Allow/Location
内容: Content-Base/Content-Encoding/Content-Language/Content-Length/Content-Location/Content-MD5/Content-Range/Content-Type
实体缓存: ETag/Expires/Last-Modified
响应状态码
100 Continue 继续, 一般在发送 post 请求时, 已发送了 http header 之后服务端将返回此信息, 表示确认, 之后发送具体参数信息
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求, 但尚未处理
206 Partial Content 响应报文包含了多个范围内的内容
301 Moved Permanently 请求的网页已永久移动到新位置
302 Found 临时性重定向
303 See Other 临时性重定向, 且总是使用 GET 请求新的 URI
304 Not Modified 自从上次请求后, 请求的网页未修改过
400 Bad Request 服务器无法理解请求的格式, 客户端不应当尝试再次使用相同的内容发起请求
401 Unauthorized 请求未授权
403 Forbidden 禁止访问
404 Not Found 找不到如何与 URI 相匹配的资源
500 Internal Server Error 最常见的服务器端错误
503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)
各版本简介
HTTP/1.0
早先的 HTTP/1.0 是一种无状态无连接的应用层协议规定浏览器和服务器保持短暂的连接, 浏览器的每次请求都需要与服务器建立一个 TCP 连接, 服务器处理完成后立即断开 TCP 连接(无连接), 服务器不跟踪每个客户端也不记录过去的请求(无状态)
这种无状态性可以借助 cookie/session 机制来做身份认证和状态记录而下面两个问题就比较麻烦了
首先, 无连接的特性导致最大的性能缺陷就是无法复用连接每次发送请求的时候, 都需要进行一次 TCP 的连接, 而 TCP 的连接释放过程又是比较费事的这种无连接的特性会使得网络的利用率非常低
其次就是就是队头阻塞 (head of line blocking) 由于 HTTP1.0 规定下一个请求必须在前一个请求响应到达之前才能发送假设前一个请求响应一直不到达, 那么下一个请求就不发送, 同样的后面的请求也给阻塞了
HTTP/1.1
长连接, 通过设置 Keep-Alive 可以保持 HTTP 连接不断开, 避免了每次客户端与服务器请求都要重复建立释放建立 TCP 连接, 提高了网络的利用率可以在请求头中携带 Connection: false 来告知服务器关闭请求
支持请求管道化(pipelining) 基于长连接, 使得请求管线化成为可能管线化使得请求能够并行传输举个例子来说, 假如响应的主体是一个 html 页面, 页面中包含了很多 img, 这个时候 keep-alive 就起了很大的作用, 能够进行并行发送多个请求(客户端依据域名来向服务器建立连接, 一般 PC 浏览器会针对单个域名的服务器同时建立 6 ~ 8 个连接, 手机端一般控制在 4 ~ 6 个这也是为什么很多大型网站设置不同的静态资源 CDN 域名来加载资源)
需要注意的是, 服务器必须按照客户端请求的先后顺序依次回送相应的结果, 以保证客户端能够区分出每次请求的响应内容
也就是说, HTTP 管道化可以让我们把先进先出队列从客户端 (请求队列) 迁移到服务端(响应队列)
http 请求图
如图所示, 客户端同时发了两个请求分别来获取 html 和 CSS, 假如说服务器的 css 资源先准备就绪, 服务器也会先发送 html 再发送 css
同时, 管道化技术只是使得客户端能够往一个服务器同时发送一组请求, 假若客户端想往这个相同的服务器发起另一组请求, 也必须等待上一组请求全部响应完毕
可见, HTTP1.1 解决队头阻塞 (head of line blocking) 还不彻底
缓存处理, 支持断点传输, 以及增加了 Host 字段(使得一个服务器能够用来创建多个 web 站点)
- HTTP/2.0
- HTTP/2 is the future of the Web
这是 Akamai 公司建立的一个官方的演示, 用以说明 HTTP/2 相比于之前的 HTTP/1.1 在性能上的大幅度提升 同时请求 379 张图片, 从 Load time 的对比可以看出 HTTP/2 在速度上的优势
顺口提一句 HTTP/2 协议是从 SPDY 演变而来, SPDY 已经完成了使命并很快就会退出历史舞台(例如 Chrome 将在 2016 年初结束对 SPDY 的支持; Nginx 已经正式支持 HTTP/2 后, 也不再支持 SPDY)
二进制分帧
HTTP2.0 通过在应用层和传输层之间增加一个二进制分帧层, 突破了 HTTP1.1 的性能限制改进传输性能
二进制分帧
可见, 虽然 HTTP2.0 的协议和 HTTP1.x 协议之间的规范完全不同了, 但是实际上 HTTP2.0 并没有改变 HTTP1.x 的语义
简单来说, HTTP2.0 只是把原来 HTTP1.x 的 header 和 body 部分用 frame 重新封装了一层而已
多路复用
下面是几个概念:
流(stream): 已建立连接上的双向字节流
消息: 与逻辑消息对应的完整的一系列数据帧
帧(frame):HTTP2.0 通信的最小单位, 每个帧包含帧首部, 至少也会标识出当前帧所属的流(stream id)
多路复用
从图中可见, 所有的 HTTP2.0 通信都在一个连接上完成, 这个连接可以承载任意数量的双向数据流
每个数据流以消息的形式发送, 而消息由一或多个帧组成这些帧可以乱序发送, 然后再根据每个帧首部的流标识符 (stream id) 重新组装
举个例子, 每个请求是一个数据流, 数据流以消息的方式发送, 而消息又分为多个帧, 帧首部记录着 stream id 用来标识所属的数据流, 不同属的帧可以在连接中随机混杂在一起接收方可以根据 stream id 将帧再归属到各自不同的请求当中去
请求优先级
多路复用导致所有资源都是并行发送, 可能会导致关键请求被阻塞那么就需要优先级的概念了, 这样就可以对重要的文件进行先传输, 加速页面的渲染
首部压缩
在 HTTP1.x 中, 首部元数据都是以纯文本的形式发送的, 通常会给每个请求增加 500~800 字节的负荷
HTTP/2.0 规定了在客户端和服务器端会使用并且维护首部表来跟踪和存储之前发送的键值对, 对于相同的头部, 不必再通过请求发送, 只需发送一次
事实上, 如果请求中不包含首部(例如对同一资源的轮询请求), 那么首部开销就是零字节此时所有首部都自动使用之前请求发送的首部
如果首部发生变化了, 那么只需要发送变化了数据在 Headers 帧里面, 新增或修改的首部帧会被追加到首部表首部表在 HTTP2.0 的连接存续期内始终存在, 由客户端和服务器共同渐进地更新
首部压缩
比如说 cookie, 默认情况下, 浏览器会在每次请求的时候, 把 cookie 附在 header 上面发送给服务器(由于 cookie 比较大且每次都重复发送, 一般不存储信息, 只是用来做状态记录和身份认证)
服务器推送
服务器除了对最初请求的响应外, 服务器还可以额外的向客户端推送资源, 而无需客户端明确的请求
在 HTTP/2 官网 可以找到更多有关 HTTP/2 协议的资料
HTTP/2 的协议协商机制?
浏览器 服务器 协商结果
不支持 HTTP/2 不支持 HTTP/2 不协商, 使用 HTTP/1.1
不支持 HTTP/2 支持 HTTP/2 不协商, 使用 HTTP/1.1
支持 HTTP/2 不支持 HTTP/2 协商, 使用 HTTP/1.1
支持 HTTP/2 支持 HTTP/2 协商, 使用 HTTP/2
HTTPS
HTTPS, 全称 Hyper Text Transfer Protocol Secure 相比 HTTP, 多了一个 Secure, 这是由 TLS(SSL)提供的 当然也可以理解为: HTTPS = HTTP + 加密 + 认证 + 完整性保护
SSL(Secure Sockets Layer 安全套接层), 及其继任者传输层安全 (Transport Layer Security,TLS) 是为网络通信提供安全及数据完整性的一种安全协议 TLS 与 SSL 在传输层对网络连接进行加密
图解 SSL/TLS 协议 - 阮一峰的网络日志 这一篇阮老师的内容写的不错. 就是时间有点久了, 目前 TLS 1.3 已经上线了, 感兴趣的可以了解下, 这个也属于性能优化的一部分(这里就大致的说下: TLS 1.2: 需要两次往返才能完成握手, 然后才能发送请求通过移动网络访问网站可以在加载时间上增加超过半秒的时间 TLS 1.3: 初始握手会减半, 只需要一次往返)
传输过程:
- HTTP => TCP => IP
- HTTP => SSL/TLS => TCP => IP
- CURL
这个其实是题外话, 因为自己调试很少用到 CURL, 了解了后才发现这东西真的很好用, 所以也就带在这里写了进去, 当给自己记录下
用法也很简单
curl[options...] < url >
具体的 options 可以用 curl -help 去查看, 这里我就说我几个会用到的
-H/--header <line> 自定义头信息传递给服务器
-X/--request <command> 指定什么命令
-d/--data <data> HTTP POST 方式传送数据
-e/--referer 来源网址
总结
如果没有时间看, 直接看这里和以第一张的思维导图如果你觉得好, 点个 star. 这个是我的 git 地址 我的 Git 地址
HTTP 是一种无状态无连接的应用层协议
现在主流的在使用的是 HTTP/1.1 (特点: 持久链接, 增加缓存处理, 支持断点传输)和 HTTP/2(特点: 二进制分帧, 首部压缩, 多路复用, 服务端推送)
HTTPS 是由 TLS(SSL)提供安全的 HTTP 协议
chrome 查看协议类型
上次看到有人提问这个, 按照以下步骤就可以了
打开检查 ... 选择到 Network
右键 Bar 勾选 protocol 即可
下图中就可以在 protocol 里看到是 http/1.1 还是 http2 了
文档参考
总结这篇学习笔记也是从很多大神的文章中和书里找到的, 感兴趣的同学可以去看下, 更深的研究欢迎大家一起来讨论学习当然我写的有问题的地方, 也麻烦各位帮助指出, 谢谢
图解 HTTP 和 HTTP 权威指南 我是先看了图解 HTTP 之后读的文章最后粗看了一下 HTTP 权威指南, 这本书很优秀, 但是其实比较厚, 所以一上来阅读比较困难, 建议看图解 HTTP, 图片可爱, 介绍的也清楚, 关键这本书页数少.
http2 讲解 . GitBook 中文翻译
HTTP1.0 HTTP1.1 HTTP2.0 主要特性对比 - 前端的那些事儿 - SegmentFault 思否
Mark Nottingham 在 Velocity Beijing 2015 的 speech , 关于 HTTP/2 下的前端性能优化相关 HTTP/2 for Front-End Developers
专题 | JerryQu 的小站
HTTP1.0 HTTP1.1 HTTP2.0 主要特性对比 - 前端的那些事儿 - SegmentFault 思否
来源: http://www.jianshu.com/p/3d1a2e37c25d