我们都知道:
-
TCP的四元组
源IP, 目标IP, 源端口, 目标端口
-
HTTP默认端口80, HTTPS默认端口443
-
AFHTTPSessionManager继承自AFURLSessionManager, 封装了常用的HTTP方法
查看相关文档
AFN的AFHTTPSessionManager
可以看到如果NSURLSessionConfiguration是background session的话, 那么AFHTTPSessionManager就必须是全局的
销毁session的方法
manager类方法
可以看到这里不是单例模式
NSURLSession的HTTPMaximumConnectionsPerHost
同一个session同一个host, iOS系统的TCP最大连接数默认是4
可以修改配置
抓包测试AFHTTPSessionManager的创建方式对网络连接的影响
使用Wireshark + Charles + 真机, 过滤下IP
观察端口列, 几张图的第一行高亮均为上一次请求的结束, 然后刷新接口
AFHTTPSessionManager非单例:
可以看到客户端的端口由50847新增了50848, 紧接着TCP三次握手
这次刷新了三个接口, 可以看到客户端的端口多了50866, 50867和50868, 紧接着都是TCP三次握手
这里的连接并不是每次请求结束就FIN的, 是过一段时间FIN或RST的
AFHTTPSessionManager单例:
请求同样的几个接口, 可以看到客户端的端口是同一个50735, 没有新增
HTTP1.1的Connection默认是keep-alive, 多个请求可以共用一个TCP连接
HTTP2实现了多路复用, 使用一个连接可以并行发送多个请求和响应, 真·全双工
如果每次请求都新建session, 新建TCP连接, 属实有些违背了HTTP1.1或HTTP2
HTTP的版本是如何选择的
先看应用启动的第一个接口
1 表示当前协议版本
2 ALPN 应用层协议协商(Application-Layer Protocol Negotiation)是一个传输层安全协议(TLS) 的扩展, ALPN 使得应用层可以协商在安全连接层之上使用什么协议, 避免了额外的往返通讯, 并且独立于应用层协议. 可以看到Client支持的有HTTP1.1和HTTP2, 而Server选择了HTTP2, 那么ALPN是什么时候传输的呢, 查看TLS的Client Hello里发现了这个扩展, 而在Server Hello里回应了选择的版本, 二者如下图
3 Client Address和Remote Address, 各自的IP和端口, 对应了TCP的四元组
4 TLS的握手流量
可以根据3和4来判断TCP连接是否复用, 在相同域名且不切换网络的情况下一般多个TCP连接里也就Client的端口号会变化
再看一下后面再次对这个接口的请求
Client的端口号未改变且没有TLS的过程, 可知连接复用了, 既节省了连接时间, 而且同一个接口的流量从1757字节降低到346字节
可见连接共用的好处还是很大的, 所以我们的代码也要尽可能支持
iOS下如何支持
iOS9开始NSURLSession支持HTTP2, AFN3.0就可以啦, 所以客户端不需要什么额外的操作, 后端的框架一般也会支持
封装session单例时可以将acceptableContentTypes封在里面, 因为一般都不会变, 而像可能有变动需求的配置如timeoutInterval就可以获取到单例对象后再设置, 甚至对于不同的securityPolicy创建多个session单例都可以, 总之, 可以根据业务需求灵活的配置
官方文档
官方对多session的创建是期望对task的不同配置