关于 iOS HTTP2.0 的一次学习实践<回顾基础>

ALPN 扩展

HTTP/2 协议本身并没有要求它必须基于
HTTPS(TLS)部署,但是出于以下三个原因,实际使用中,HTTP/2 和 HTTPS
几乎都是捆绑在一起:

  • HTTP 数据明文传输,数据很容易被中间节点窥视或篡改,HTTPS
    可以保证数据传输的保密性、完整性和不被冒充;
  • 正因为 HTTPS 传输的数据对中间节点保密,所以它具有更好的连通性。基于
    HTTPS 部署的新协议具有更高的连接成功率;
  • 当前主流浏览器,都只支持基于 HTTPS 部署的 HTTP/2;

如果前面两个原因还不足以说服你,最后这个绝对有说服力,除非你的 HTTP/2
服务只打算给自己客户端用。

下面介绍在 HTTPS 中,浏览器和服务端之间怎样协商是否使用 HTTP/2。

基于 HTTPS 的协议协商非常简单,多了 TLS 之后,双方必须等到成功建立 TLS
连接之后才能发送应用数据。而要建立 TLS 连接,本来就要进行 CipherSuite
等参数的协商。引入 HTTP/2 之后,需要做的只是在原本的协商机制中把对 HTTP
协议的协商加进去。

Google 在 SPDY 协议中开发了一个名为 NPN(Next Protocol
Negotiation,下一代协议协商)的 TLS 扩展。随着 SPDY 被 HTTP/2 取代,NPN
也被官方修订为 ALPN(Application Layer Protocol
Negotiation,应用层协议协商)。二者的目标和实现原理基本一致,这里只介绍后者。如图:

网赌平台哪个信誉好 1

可以看到,客户端在建立 TLS 连接的 Client Hello 握手中,通过 ALPN
扩展列出了自己支持的各种应用层协议。其中,HTTP/2 协议名称是 h2

网赌平台哪个信誉好 2

如果服务端支持 HTTP/2,在 Server Hello 中指定 ALPN 的结果为 h2
就可以了;如果服务端不支持 HTTP/2,从客户端的 ALPN
列表中选一个自己支持的即可。

并不是所有 HTTP/2 客户端都支持 ALPN,理论上建立 TLS
连接后,依然可以再通过 HTTP Upgrade
进行协议升级,只是这样会额外引入一次往返。

消息:消息由帧组成

小结

看到这里,相信你一定可以很好地回答本文开头提出的问题。

HTTP/2 需要基于 HTTPS 部署是当前主流浏览器的要求。如果你的 HTTP/2
服务要支持浏览器访问,那就必须基于 HTTPS
部署;如果只给自己客户端用,可以不部署
HTTPS(这个页面列举了很多支持
h2c 的 HTTP/2 服务端、客户端实现)。

支持 HTTP/2 的 Web Server 基本都支持 HTTP/1.1。这样,即使浏览器不支持
HTTP/2,双方也可以协商出可用的 HTTP 版本,没有兼容性问题。如下表:

浏览器 服务器 协商结果
不支持 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

当然,本文讨论的是通用情况。对于自己实现的客户端和服务端,如果打算使用
HTTP/2 ClearText,由于 HTTP Upgrade
协商会增加一次往返,可以要求双方必须支持 HTTP/2,直接发送 HTTP/2
数据,不走协商。

打赏支持我写出更多好文章,谢谢!


打赏作者

再者简单粗暴,直接在 iOS 代码中打印,_CFURLResponse 中包含了
httpversion,获取方法就是基于 CFNetwork 相关的 API
来做,这里直接丢出关键代码,完整代码可以参考getHTTPVersion

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

网赌平台哪个信誉好 3
网赌平台哪个信誉好 4

1 赞 1 收藏
评论

流:一个Stream是包含一条或多条信息、ID和优先级的双向通道

谈谈 HTTP/2 的协议协商机制

2016/04/16 · 基础技术 ·
HTTP/2

本文作者: 伯乐在线
JerryQu
。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者

文章目录

在过去的几个月里,我写了很多有关 HTTP/2
的文章,也做过好几场相关分享。我在向大家介绍 HTTP/2
的过程中,有一些问题经常会被问到。例如要部署 HTTP/2 一定要先升级到 HTTPS
么?升级到 HTTP/2 之后,不支持 HTTP/2
的浏览器还能正常访问么?本文重点介绍 HTTP/2
的协商机制,明白了服务端和客户端如何协商出最终使用的 HTTP
协议版本,这两个问题就迎刃而解了。

一切准备就绪之后,也是时候对结果进行验证了,除了刚才提到的 WireShark
之外,你还可以使用下面的几个工具来对 HTTP 2.0 进行测试

关于作者:JerryQu

网赌平台哪个信誉好 5

专注 Web 开发,关注 Web
性能优化与安全。https://imququ.com
个人主页
·
我的文章
·
2
·
 网赌平台哪个信誉好, 

网赌平台哪个信誉好 6

帧:帧有不同的类型,并且是混合的。他们通过stream id被重新组装进消息中

HTTP Upgrade

为了更方便地部署新协议,HTTP/1.1 引入了 Upgrade
机制,它使得客户端和服务端之间可以借助已有的 HTTP
语法升级到其它协议。这个机制在 RFC7230 的「6.7
Upgrade
」这一节中有详细描述。

要发起 HTTP/1.1 协议升级,客户端必须在请求头部中指定这两个字段:

Connection: Upgrade Upgrade: protocol-name[/protocol-version]

1
2
Connection: Upgrade
Upgrade: protocol-name[/protocol-version]

客户端通过 Upgrade
头部字段列出所希望升级到的协议和版本,多个协议之间用 ,(0x2C,
0x20)隔开。除了这两个字段之外,一般每种新协议还会要求客户端发送额外的新字段。

如果服务端不同意升级或者不支持 Upgrade
所列出的协议,直接忽略即可(当成 HTTP/1.1 请求,以 HTTP/1.1
响应);如果服务端统一升级,那么需要这样响应:

HTTP/1.1 101 Switching Protocols Connection: upgrade Upgrade:
protocol-name[/protocol-version] [… data defined by new protocol
…]

1
2
3
4
5
HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: protocol-name[/protocol-version]
 
[… data defined by new protocol …]

可以看到,HTTP Upgrade 响应的状态码是
101,并且响应正文可以使用新协议定义的数据格式。

如果大家之前使用过 WebSocket,应该已经对 HTTP Upgrade
机制有所了解。下面是建立 WebSocket 连接的 HTTP 请求:

GET ws://example.com/ HTTP/1.1 Connection: Upgrade Upgrade: websocket
Origin: http://example.com Sec-WebSocket-Version: 13 Sec-WebSocket-Key:
d4egt7snxxxxxx2WcaMQlA== Sec-WebSocket-Extensions: permessage-deflate;
client_max_window_bits

1
2
3
4
5
6
7
GET ws://example.com/ HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Origin: http://example.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: d4egt7snxxxxxx2WcaMQlA==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

这是服务端同意升级的 HTTP 响应:

HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: websocket
Sec-WebSocket-Accept: gczJQPmQ4Ixxxxxx6pZO8U7UbZs=

1
2
3
4
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: gczJQPmQ4Ixxxxxx6pZO8U7UbZs=

在这之后,客户端和服务端之间就可以使用 WebSocket
协议进行双向数据通讯,跟 HTTP/1.1 没关系了。可以看到,WebSocket
连接的建立就是典型的 HTTP Upgrade 机制。

显然,这个机制也可以用做 HTTP/1.1 到 HTTP/2 的协议升级。例如:

GET / HTTP/1.1 Host: example.com Connection: Upgrade, HTTP2-Settings
Upgrade: h2c HTTP2-Settings:

1
2
3
4
5
GET / HTTP/1.1
Host: example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings:

在 HTTP Upgrade 机制中,HTTP/2 的协议名称是 h2c,代表 HTTP/2
ClearText。如果服务端不支持 HTTP/2,它会忽略 Upgrade 字段,直接返回
HTTP/1.1 响应,例如:

HTTP/1.1 200 OK Content-Length: 243 Content-Type: text/html …

1
2
3
4
5
HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html
 

如果服务端支持 HTTP/2,那就可以回应 101
状态码及对应头部,并且在响应正文中可以直接使用 HTTP/2 二进制帧:

HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: h2c [
HTTP/2 connection … ]

1
2
3
4
5
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
 
[ HTTP/2 connection … ]

以下是通过 HTTP Upgrade 机制将 HTTP/1.1 升级到 HTTP/2 的 Wireshark
抓包(两张图可以对照来看):

网赌平台哪个信誉好 7

网赌平台哪个信誉好 8

根据 HTTP/2 协议中的描述,额外补充几点:

  • 41 号包中,客户端发起的协议升级请求中,必须通过 HTTP2-Settings
    指定一个经过 Base64 编码过的 HTTP/2 SETTINGS 帧;
  • 45 号包中,服务端同意协议升级,响应正文中必须包含 HTTP/2 SETTING
    帧(二进制格式,不需要 Base64 编码);
  • 62 号包中,客户端可以开始发送各种 HTTP/2 帧,但第一个帧必须是 Magic
    帧(内容固定为 PRI * HTTP/2.0rnrnSMrnrn),做为协议升级的最终确认;

HTTP Upgrade
机制本身没什么问题,但很容易受网络中间环节影响。例如不能正确处理
Upgrade 头部的代理节点,很可能造成最终升级失败。之前我们统计过
WebSocket 的连通情况,发现大量明明支持 WebSocket
的浏览器却无法升级,只能使用降级方案。

NPN 的协商结果是在 Change Cipher Spec 之后加密发送给服务端;而 ALPN
的协商结果是通过 Server Hello 明文发给客户端

服务端收到这个请求后,如果支持 Upgrade 中 列举的协议,这里是
h2c,就会返回支持的响应:

下面,就开始通过查看 TLS 握手的过程分析HTTP2.0 的协商过程,刚才也说道
ALPN 协商结果是在 Client hello 和 Server hello
中显示的,那就先来看一下Client hello

同时,目前很多地方开始停止对NPN的支持,仅支持
ALPN,所以公司使用的话,最佳是直接使用 ALPN。

使用 NSURLSession 代替 NSURLConnection

这个是h2的协商过程,对于刚才提到的 h2c 的协商过程,与此不同,h2c
利用的是HTTP Upgrade 机制,客户端会发送一个 http
1.1的请求到服务端,这个请求中包含了 http2的升级字段,例如:

Server
Push:就是服务端可以主动推送一些东西给客户端,也被称为缓存推送。推送的资源可以备客户端日后之需,需要的时候直接拿出来用,提升了速率。具体的实验可以参考这里:iOS
HTTP/2 Server Push 探索

网赌平台哪个信誉好 9

Chrome 上的一个插件,HTTP/2 and SPDY indicator会在你访问 http2.0
的网页的时候,以小闪电的形式进行指示

针对同一域名,在请求较多的情况下,HTTP1.1
会开辟多个连接,据说浏览器一般是6-8
个,较多连接也会导致延迟增大,资源消耗等问题

除了上面讲到的特性,HTTP2.0
还有流量控制、流优先级和依赖性等功能。更多细节可以参考:Hypertext
Transfer Protocol Version 2

虽然 HTTP1.1 默认是开启 Keep-Alive
长连接的,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点,但是依然存在
head of line
blocking,如果出现一个较差的网络请求,会影响后续的网络请求。为什么呢?如果你发出1、2、3
三个网络请求,那么 Response 的顺序 2、3 要在第一个网络请求之后,以此类推

HTTP 1.1

HTTP2.0

网赌平台哪个信誉好 10

客户端系统版本 iOS 9 +

网赌平台哪个信誉好 11

可以看到客户端在 Client hello 中列出了自己支持的各种应用层协议,比如
spdy3、h2。那么接着看 Server hello 是如何回复的

分享之前我还是要推荐下我自己建的iOS开发学习群:680565220,群里都是学ios开发的,如果你正在学习ios
,小编欢迎你加入,今天分享的这个案例已经上传到群文件,大家都是软件开发党,不定期分享干货(只有iOS软件开发相关的),包括我自己整理的一份2017最新的iOS进阶资料和高级开发教程,欢迎进阶中和进想深入iOS的小伙伴。

iOS 如何接入 HTTP 2.0呢?其实很简单:

HTTP 2.0的协商机制

网赌平台哪个信誉好 12

网赌平台哪个信誉好 13

网赌平台哪个信誉好 14

服务端会根据 client hello
中的协议列表,发过去自己支持的网络协议,假如服务端支持
h2,则直接返回h2,协商成功,如果不支持
h2,则返回一个其他支持的协议,比如HTTP1.1、spdy3

下面就直接来看看 ALPN 的协商过程是怎样的,ALPN 作为 TLS
的一个扩展,其过程可以通过 WireShark 查看 TLS握手过程来查看

网赌平台哪个信誉好 15

前面的文章也提到了目前的移动端网络常见性能问题,以及对应的优化策略,如果把HTTP1.1
替换为 HTTP2.0,可以说是网络性能优化的一步大棋。这几天对 iOS HTTP2.0
进行了简单的调研、测试,在此做个简单的总结

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图