HTTP
- 超文本传输协议(HyperText Transfer Protocol)
- 客户端与服务器应答标准
- 基于TCP/IP协议的应用层协议
- 91年发布HTTP/0.9,96年HTTP/1.0, 99年HTTP/1.1
- 2015年HTTP/2 Spec 发布 RFC 7540
HTTP/0.9 - HTTP/1.1
- 0.9仅有一个Get方法
- 1.0增加若干内容如Post Head,不支持永久TCP连接...
- 1.1版本增加更多内容,支持持久连接,管道机制,缓存...
HTTP面临的问题
- TCP不能够充分被利用
- 网络差就会延迟
- 目前优化HTTP的方案都比较繁琐
- HTTP包含太多的细节和可选部分,过于庞大
- HTTP Pipelinging(通过管线提高TCP利用率),会队头阻塞(Head-of-line blocking)
- 延迟,HTTP Streaming延迟
- 请求的内容越来越大
目前的解决方法
- 合并脚本
- 样式表
- 图片嵌入CSS
- 域名分片
SPDY(Speed)
- 由Google开发,设计目的在于降低网页的加载时间
- SPDY不用于替换HTTP,只是修改了HTTP的传输方式
- 有多路复用,优先级,和压缩的特性
- 仅支持在TLS(安全传输层协议)层
- SPDY是Google的注册商标
HTTP/2
- 基于SPDY草案修改
- 在现有协议上之上构建的新协议,保留现有
- 更好的利用TCP特性来减少传输过程中的等待和暂停
- 更好的Web体验
- HTTP/2 是google开发的 SPDY协议的一个子集
- 解决队头阻塞(Head-of-line blocking)问题
- 下一个协议是HTTP/3
- RFC 7540
HTTP/2特性
与HTTP1.x兼容
使用NPN或者ALPN在请求之前确定应该如何使用哪种协议来通讯.
- ALPN(Application Layer Protocol Negotiation)(HTTP2)
- NPN(Next Protocol Negotiation)(SYPD)
NPN与ALPN的区别在于: 谁来决定会话所使用的协议
ALPN:客户端先发送一个协议优先级列表给服务器,有服务器选择合适的
NPN:服务通知客户端所有它支持的格式,客户端来选合适的进行通信
NPN已经被ALPN取代
二进制协议
- HTTP由文本协议变成二进制协议
- 为了更好的实现成帧,使用文本再数据处理会很繁琐
- 一个帧包含数据帧和头帧
-
使用curl或者Wireshark来解析
帧
- 连接建立之后之后用帧来传输数据
- Length表示帧的大小
- Type类型定义了剩余的帧报头和帧主体将如何被解释
- Flags在不同帧类型赋予不同的语义
- StreamIdentifier流的标识符号,用于确定是那个流的帧
- FramePayload 数据
- 目前已定义的帧有10种DATA、HEADERS、PRIORITY 、RST_STREAM、SETTINGS、PUSH_PROMISE、PING、GOAWAY、WINDOW_UPDATE、CONTINUATION
多路复用Multiplexing
- 在一个TCP连接里,可以发送多个请求或回应,可以不按照顺序发送
Multiplexing 在一个TCP连接里,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分,接着回应B请求,完成后,再发送A请求剩下的部分。 ——
数据流
- 每个请求或回应的数据包为一个流
- 每个流都会有一个StreamID,由启动流的终端分配
- 客户端可以定义流的并发量
优先级和依赖性
- 每个的帧头都会包含流的优先级标识
- 可以根据优先级帧来调整已经发送的流的优先级
- 没有明确指定使用默认值
- 流可以显示依赖其他流
头压缩 HPack
- HTTP属于无状态协议,表示每次请求都会携带相同的信息,为了减少冗余信息使用了HPACK机制来对请求头进行压缩
- 使用了默认的Static Table 和 可以由客户端添加字段的Dynamic Table
- 使用哈夫曼编码
- 压缩效率高效
- RFC 7541
中断请求
- 如果想取消一个请求只需要发送RST_STREAM 帧就可以了
服务器推送
- 可以在没有请求的情况下主动向客户端推送内容
- 客户端可以选择是否中断推送
ServerPush-1294
HTTP连接管理
HTTP/2连接是永久性的。为了最佳的性能,它期待直到确定与服务端的进一步沟通不再必要的时候,客户端才会关闭连接(例如,当用户导航到其他特定的网页),或者直到服务端关闭连接。
Chrome Debug
使用Node.js 搭建一个建议HTTP2服务器
https://github.com/molnarg/node-http2-
使用Developer Tools来查看HTTP与HTTP/2的区别
可以看出HTTP/2使用一条TCP连接完成所有的资源请求
查看HTTP/2的建立与帧传输
chrome://net-internals/#http2WireShark也支持抓包,不过因为HTTP/2走了TLS,所以要做一些代理处理,不做解释。
Mobie
iOS
NSURLSession
- NSURLSession在iOS9.0之支持HTTP/2,SYPD
- 开发者不需做修改
- iOS10之后支持调试可查看请求使用的协议
- 推测通过NSURLSession通过curl实现HTTP2...(经过ida拆解只找到使用了和curl相同的HTTP/2头解析库😭)
ASPN
- New provider API
- ASPN服务使用HTTP/2来实现,通过减少TCP连接大幅度提升服务器效率,减少服务端压力
总结
iOS同学基本上,如果使用了URLSession去做网络请求可以啥都不用干,只要Server支持HTTP/2就可以了
Android
没有写过安卓...本部分仅参考
OKHttp
- 安卓端的一个HTTP的实现
- JAVA实现了HTTP/2
- 据Android同学SK IMSK 分享,该库在重用TCP方面做的非常好
REF
http://kamranahmed.info/blog/2016/08/13/http-in-depth/ HTTP协议简介
https://github.com/square/okhttp 安卓Http网络请求的实现
https://github.com/kylef/hpack.swift hpackSwift实现
https://github.com/curl/curl libcurl
https://github.com/nghttp2/nghttp2 curl里HPack的实现
https://github.com/apple/swift-corelibs-foundation Swift版本Foundation实现
http://opensource.apple.com/source/CF/CF-1153.18/
https://http2.github.io/
http://httpwg.org/specs/rfc7540.html RFC7540 HTTP2.0详细实现
http://www.chromium.org/spdy/spdy-whitepaper
https://developer.apple.com/videos/play/wwdc2016/711/ NSURLSession: New Features and Best Practices
https://developer.apple.com/videos/play/wwdc2015/711/ Networking with NSURLSession
https://developer.apple.com/videos/play/wwdc2015/720/ What’s New in Notifications
https://developer.apple.com/videos/play/wwdc2015/724/
What’s New in Apple Push Notification Service