本篇文章作为网络通信相关知识点的第三篇文章,大家在看这篇文章之前,可以先看前面的两篇文章,毕竟主要的知识点主要还是分为了三个部分进行讲解,下面是前面两篇文章:
网络通信相关知识详解(一)
网络通信相关知识详解(二)
相关知识点汇总:
一、手机与外界通信的手段
二、描述一次网络请求的流程
三、网络七层模型介绍
四、网络相关设备详解(路由器,交换机,网桥,网关)
五、TCP/IP协议族与相关知识(三次握手,四次挥手,流量控制,拥塞控制)
六、cookie,sessionId与token的区别
七、网络数据传输类型的处理(文字,图片,实时音频流,实时视频流,文件)
八、数据指纹,数据签名,数字证书的概念
九、Base64、对称加密算法、非对称加密算法、数据摘要的概念
十、Http与Https知识点详解
十一、基于TCP的Socket与基于UDP的Socket通信
十二、常见网络攻击手段与防护(重放攻击,中间人攻击,流量劫持)
十三、HttpClient,HttpUriConnection与Okhttp的区别
十四、Http 1.0,Http 1.1,Http 2.0,SPDY,Http 3.0的区别
十五、网络请求框架对比:AndroidAsync-httpClient,Volley,Okhttp,Retrofit
十六、Bio,Nio,Aio的区别
十七、网络性能优化
十八、扩展阅读
十二、常见网络攻击手段与防护(重放攻击,中间人攻击)
重放攻击:入侵者从网络上截取主机A发送给主机B的报文,并把由A加密的报文发送给B,使主机B误以为入侵者就是主机A,然后主机B向伪装成A的入侵者发送应当发送给A的报文。
防御手段:
手段一:加随机数
该方法优点是认证双方不需要时间同步,双方记住使用过的随机数,如发现报文中有以前使用过的随机数,就认为是重放攻击。缺点是需要额外保存使用过的随机数,若记录的时间段较长,则保存和查询的开销较大。
手段二:加时间戳
该方法优点是不用额外保存其他信息。缺点是认证双方需要准确的时间同步,同步越好,受攻击的可能性就越小。但当系统很庞大,跨越的区域较广时,要做到精确的时间同步并不是很容易。
手段三:加流水号
就是双方在报文中添加一个逐步递增的整数,只要接收到一个不连续的流水号报文(太大或太小),就认定有重放威胁。该方法优点是不需要时间同步,保存的信息量比随机数方式小。缺点是一旦攻击者对报文解密成功,就可以获得流水号,从而每次将流水号递增欺骗认证端。
附加:对付重放攻击除了使用以上方法外,还可以使用挑战一应答机制和一次性口令机制,而且似乎后面两种方法在实际中使用得更广泛。
中间人攻击(MiTM):
描述:当数据传输发生在一个设备(PC/手机)和网络服务器之间时,攻击者使用其技能和工具将自己置于两个端点之间并截获数据;尽管交谈的两方认为他们是在与对方交谈,但是实际上他们是在与干坏事的人交流,这便是中间人攻击。
中间人攻击(MiTM)的几种方式:
方式一:嗅探
嗅探或数据包嗅探是一种用于捕获流进和流出系统/网络的数据包的技术。网络中的数据包嗅探就好像电话中的监听。记住,如果使用正确,数据包嗅探是合法的;许多公司出于“安全目的”都会使用它。
方式二:数据包注入
在这种技术中,攻击者会将恶意数据包注入常规数据中。这样用户便不会注意到文件/恶意软件,因为它们是合法通讯流的一部分。在中间人攻击和拒绝式攻击中,这些文件是很常见的。
方式三:会话劫持
会话劫持”(SessionHijack)是一种结合了嗅探以及欺骗技术在内的攻击手段。广义上说,会话劫持就是在一次正常的通信过程中,攻击者作为第三方参与到其中,或者是在数据里加入其他信息,甚至将双方的通信模式暗中改变,即从直接联系变成有攻击者参与的联系。
方式四:SSL剥离
SSL剥离或SSL降级攻击是MiTM攻击的一种十分罕见的方式,但是也是最危险的一种。众所周知,SSL/TLS证书通过加密保护着我们的通讯安全。在SSL剥离攻击中,攻击者使SSL/TLS连接剥落,随之协议便从安全的HTTPS变成了不安全的HTTP。
方式五:DNS欺骗
攻击者通过入侵DNS服务器、控制路由器等方法把受害者要访问的目标机器域名对应的IP解析为攻击者所控制的机器,这样受害者原本要发送给目标机器的数据就发到了攻击者的机器上,这时攻击者就可以监听甚至修改数据,从而收集到大量的信息。
如何防止中间人攻击:
对于DNS欺骗,要记得检查本机的HOSTS文件,以免被攻击者加了恶意站点进去;其次要确认自己使用的DNS服务器是ISP提供的,因为当前ISP服务器的安全工作还是做得比较好的,一般水平的攻击者无法成功进入;如果是依靠网关设备自带的DNS解析来连接Internet的,就要拜托管理员定期检查网关设备是否遭受入侵。
至于局域网内各种各样的会话劫持(局域网内的代理除外),因为它们都要结合嗅探以及欺骗技术在内的攻击手段,必须依靠ARP和MAC做基础,所以网管应该使用交换式网络(通过交换机传输)代替共享式网络(通过集线器传输),这可以降低被窃听的机率,当然这样并不能根除会话劫持,还必须使用静态ARP、捆绑MAC+IP等方法来限制欺骗,以及采用认证方式的连接等。
十三:HttpClient,HttpUriConnection与Okhttp的区别
对比图:
HttpClient:HttpClient是Apache的一个三方网络框架,网络请求做了完善的封装,api众多,用起来比较方便,开发快。实现比较稳定,bug比较少,但是正是由于其api众多,是我们很难再不破坏兼容性的情况下对其进行扩展。所以,Android团队对提升和优化httpclient积极性并不高。android5.0被废弃,6.0逐渐删除。
HttpURLConnection:HttpURLConnection是一个多用途、轻量级的http客户端。它对网络请求的封装没有HttpClient彻底,api比较简单,用起来没有那么方便。但是正是由于此,使得我们能更容易的扩展和优化的HttpURLConnection。不过,再android2.2之前一直存在着一些令人烦的bug,比如一个可读的inputstream调用它的close方法的时候,会使得连接池实效,通常的做法就是禁用连接池。因此,在android2.2之前建议使用稳定的HttpClient,android2.2之后使用更容易扩展和优化的HttpURLConnection。
OkHttp:OkHttp是一个现代,快速,高效的Http client,支持HTTP/2以及SPDY(SPDY介绍网址:https://zh.wikipedia.org/wiki/SPDY,SPDY(发音如英语:speedy),一种开放的网络传输协议,由Google开发),它为你做了很多的事情。
优点:
1、支持SPDY,可以合并多个到同一个主机的请求
2、OkHttp实现的诸多技术如:连接池,gziping,缓存等网络相关的操作。
3、OkHttp使用Okio来大大简化数据的访问与存储,Okio是一个增强java.io和java.nio的库。
4、OkHttp处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP,OKHttp会自动处理常见的网络问题,像二次连接、SSL的握手问题。
5、OkHttp还处理了代理服务器问题和SSL握手失败问题。
6、缓存响应避免重复的网络请求。
附加:
1、OkHttp是一个Java的HTTP+SPDY客户端开发包,同时也支持Android。
2、从Android4.4开始HttpURLConnection的底层实现采用的是okHttp。
十四:Http 1.0,Http 1.1,Http 2.0,SPDY,Http 3.0的区别及相关知识点
HTTP的基本优化:
影响一个HTTP网络请求的因素主要有两个:带宽和延迟。
带宽:如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。
延迟:
1、浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有4个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。
2、DNS查询(DNS Lookup):浏览器需要知道目标服务器的IP才能建立连接。将域名解析为IP的这个系统就是DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
3、建立连接(Initial connection):HTTP是基于TCP协议的,浏览器最快也要在第三次握手时才能捎带HTTP请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
HTTP 1.0和HTTP 1.1的一些区别:
区别一:缓存处理,在HTTP 1.0中主要使用header里的If-Modified-Since、Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
区别二:带宽优化及网络连接的使用,HTTP 1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP 1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
区别三:错误通知的管理,在HTTP 1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
区别四:Host头处理,在HTTP 1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP 1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
区别五:长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP 1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP 1.0每次请求都要创建连接的缺点。
SPDY:HTTP 1.x的优化
2012年google如一声惊雷提出了SPDY的方案,优化了HTTP 1.X的请求延迟,解决了HTTP1.X的安全性,具体如下:
1、降低延迟:针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个TCP连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率。
2、请求优先级(request prioritization):多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。
3、header压缩:前面提到HTTP 1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。
4、基于HTTPS的加密协议传输,大大提高了传输数据的可靠性。
5、服务端推送(server push):采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。
一:HTTP2.0和SPDY的区别
1、HTTP 2.0支持明文HTTP传输,而SPDY强制使用HTTPS
2、HTTP 2.0消息头的压缩算法采用HPACK,而非SPDY采用的DEFLATE。
二:HTTP 2.0和HTTP 1.X相比的新特性
1、新的二进制格式(Binary Format):HTTP 1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP 2.0的协议解析决定采用二进制格式,实现方便且健壮。
2、多路复用(MultiPlexing):即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的id将request再归属到各自不同的服务端请求里面。
3、header压缩:如上文中所言,对前面提到过HTTP 1.x的header带有大量信息,而且每次都要重复发送,HTTP 2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
4、服务端推送(server push):同SPDY一样,HTTP2.0也具有server push功能。
QUIC协议浅析与HTTP/3.0:
简介:QUIC(Quick UDP Internet Connections)基于UDP的传输层协议,提供像TCP一样的可靠性。在提高web应用性能上,可以选择在应用层使用HTTP 2.0实现多路传输,在物理层使用CDN解决网络拥塞和最后一公里问题。在传输层,目前主要使用TCP,但由于TCP本身的问题(一个充满补丁的丑陋的协议),成为了限制web应用性能的一个瓶颈。
QUIC是Google新开发的一个基于UDP的协议,它提供了像TCP一样的传输可靠性保证,可以实现数据传输的0-RTT延迟,灵活的设计使我们可以对它的拥塞控制及流量控制做更多的定制,它还提供了传输的安全性保障,以及像HTTP/2一样的应用数据二进制分帧传输。
特性:
一:对线头阻塞(HOL)问题的解决更为彻底
基于TCP的HTTP/2,尽管从逻辑上来说,不同的流之间相互独立,不会相互影响,但在实际传输方面,数据还是要一帧一帧的发送和接收,一旦某一个流的数据有丢包,则同样会阻塞在它之后传输的其它与它毫不相干的流的数据的传输。而基于UDP的QUIC协议则可以更为彻底地解决这样的问题,让不同的流之间真正的实现相互独立传输,互不干扰。
二:切换网络时的连接保持
当前移动端的应用环境,用户的网络可能会经常切换,比如从办公室或家里出门,WiFi断开,网络切换为3G或4G。基于TCP的协议,由于切换网络之后,IP会改变,因而之前的连接不可能继续保持。而基于UDP的QUIC协议,则可以内建与TCP中不同的连接标识方法,从而在网络完成切换之后,恢复之前与服务器的连接。
附加:HTTP 3.0将TCP协议更换为基于UDP的谷歌QUIC。
google的QUIC协议从TCP切换到UDP时,优势如下:
机制一:自定义连接机制
一条tcp连接是由四元组标识的,分别是源IP、源端口、目的源IP、目的源端口,一旦一个元素发生变化时,就会断开重连,重新连接。
机制二:自定义重传机制
tcp为了保证可靠性,通过使用序号和应答机制,来解决顺序问题和丢包问题。
机制三: 无阻塞的多路复用
有了自定义的连接和重传机制,就可以解决上面HTTP 2.0的多路复用问题同HTTP 2.0一样,同一条QUIC连接上可以创建多个stream,来发送多个HTTP请求,但是,QUIC是基于UDP的,一个连接上的多个stream之间没有依赖。这样,假如stream2丢了一个UDP包,后面跟着stream3的一个UDP包,虽然stream2的那个包需要重新传,但是stream3的包无需等待,就可以发给用户。
机制四:自定义流量控制
TCP的流量控制是通过滑动窗口协议。QUIC的流量控制也是通过window_update,来告诉对端它可以接受的字节数。但是QUIC的窗口是适应自己的多路复用机制的,不但在一个连接上控制窗口,还在一个连接中的每个steam控制窗口。
一:HTTP 2.0的多路复用和HTTP 1.X中的长连接复用有什么区别?
1、HTTP 1.*一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;
2、HTTP 1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;
3、HTTP 2.0 多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行;
总结:http 2.0成功解决了http1.1的队首阻塞问题,同时,也不需要通过 http1.x的pipeline机制用多条tcp连接来实现并行请求和响应;减少了tcp连接数对服务器性能的影响,同时将页面的多个数据css,js,jpg等通过一个数据链接进行传输,能够加快页面组件的传输速度。
二:服务器推送到底是什么?
服务端推送能把客户端所需要的资源(例如js资源,css,jpg)伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。
三:为什么需要头部压缩?
假定一个页面有100个资源需要加载(这个数量对于今天的Web而言还是挺保守的),而每一次请求都有1kb的消息头(这同样也并不少见,因为Cookie和引用等东西的存在),则至少需要多消耗100kb来获取这些消息头。HTTP 2.0可以维护一个字典,差量更新HTTP头部,大大降低因头部传输产生的流量。
四:HTTP2.0多路复用有多好?
HTTP性能优化的关键并不在于高带宽,而是低延迟。TCP连接会随着时间进行自我调节,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调节则被称为TCP慢启动。由于这种原因,让原本就具有突发性和短时性的HTTP连接变的十分低效。
HTTP 2.0 通过让所有数据流共用同一个连接,可以更有效地使用TCP连接,让高带宽也能真正的服务于HTTP的性能提升。
十五:网络请求框架对比:AndroidAsync-httpClient,Volley,Okhttp,Retrofit
框架一:Android-async-http
原理:基于HttpClient
功能特色:
1、自动请求重试
2、持久化cookie存储
性能,使用方式,应用场景:无
附加:不推荐使用,作者已停止维护,Android 5.0弃用httpClient。
框架二:Volley
原理:基于HttpUrlConnection
功能特色:
1、支持图片加载(封装了图片记载库UIL)
2、网络请求排序、优先级处理
3、缓存
4、生命周期与Activity联动(即Activity结束时,取消所有相关网络请求)
性能:
1、扩展性好,即支持HttpClient,HttpUrlConnection,Okhttp
使用方式:
2、简单易用
应用场景:
1、频繁的,数据量少的轻量级网络请求
2、不适合大数据的网络请求,如下载音频,视频/文件,Request和Response都是把数据放到Byte数组中,若数据大,数组大,耗费内存。
框架三:Okhttp
原理:基于原生HTTP
功能特色:
1、支持同步和异步请求
2、支持GZIP减少数据流量
3、缓存响应数据(从而减少重复的网络请求)
4、自动重连(处理了代理服务器问题和SSL握手失败问题)
5、支持SPDY(共享同个Socket来处理同一个服务器的请求,若SPDY不可用,则通过链接池来减少请求延迟)
性能:
1、基于NIO、Okio
2、NIO:非阻塞式
3、Okio:Square基于IO、NIO的一个高效处理数据流的开源库
使用方式:
2、API使用更加方便,简单(需要进一步封装)
应用场景:
1、数据量大的重量级网络请求
框架四:Retrofit
原理:基于Okhttp
功能特色:
1、Okhttp的功能特点
2、通过注解配置请求
3、序列化方式丰富(Gson,ProtocalBuffer等)
4、提供Rxjava支持
5、RESTFUL API设计风格
性能:
1、请求、处理速度最快
2、扩展性差:封装性太好(如解析数据是使用统一的Converter)
使用方式:
1、使用最简单、最方便、代码量少(封装性最好,注解用法、RESTFUL API)
2、解耦更加彻底
3、易与其他框架联用,如Rxjava
应用场景:
1、任何场景优先使用
2、特别是存在额外开发需求时,如项目中使用到Rxjava,多样的数据序列化方式和后台API为RESTFUL风格
十六、Bio,Nio,Aio的区别(服务器的角度)
IO的方式通常分为:同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。
一、BIO
在JDK 1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程响应,如果没有则会一直等待或者遭到拒绝请求,如果有的话,客户端会线程会等待请求结束后才继续执行。
二、NIO
NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题: 在使用同步I/O的网络应用中,如果要同时处理多个客户端请求,或是在客户端要同时和多个服务器进行通讯,就必须使用多线程来处理。也就是说,将每一个客户端请求分配给一个线程来单独处理。这样做虽然可以达到我们的要求,但同时又会带来另外一个问题。由于每创建一个线程,就要为这个线程分配一定的内存空间(也叫工作存储器),而且操作系统本身也对线程的总数有一定的限制。如果客户端的请求过多,服务端程序可能会因为不堪重负而拒绝客户端的请求,甚至服务器可能会因此而瘫痪。
总结:NIO的最重要的地方是当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面,所以所有的连接只需要一个线程就可以搞定,当这个线程中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式。
在NIO的处理方式中,当一个请求来的话,开启线程进行处理,可能会等待后端应用的资源(JDBC连接等),其实这个线程就被阻塞了,当并发上来的话,还是会有BIO一样的问题。
三、AIO
与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序,即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。
总结:
1、BIO是一个连接一个线程。
2、NIO是一个请求一个线程。
3、AIO是一个有效请求一个线程。
BIO、NIO、AIO适用场景分析:
1、BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK 1.4以前的唯一选择,但程序直观简单易理解。
2、NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK 1.4开始支持。
3、AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK 7开始支持。
一般来说I/O模型可以分为:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO
1、同步阻塞IO:在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式!
2、同步非阻塞IO:在此种方式下,用户进程发起一个IO操作以后,可边做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。
3、异步阻塞IO:此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄,从而提高系统的并发性!
4、异步非阻塞IO:在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。目前Java中还没有支持此种IO模型。
十七:网络性能优化
优化哪些方面:
1、速度:在网络正常或者良好的时候,怎样更好地利用带宽,进一步提升网络请求的速度。
2、弱网络:移动端网络复杂多变,在出现网络连接不稳定的时候,怎样最大程度保证网络的连贯性。
3、安全:网路安全不容忽视,怎样有效防止被第三方劫持、窃听甚至篡改。
除了这三个问题,我们还可能会关心网络请求造成的耗电、流量问题。
一次网络请求的流程图和耗时比较图:
由上图可以看到,整个网络请求主要分为几个步骤,而整个请求耗时可以细分到每一个步骤里面。
步骤一:DNS解析
通过DNS服务器,拿到对应域名的IP地址。在这个步骤,我们比较关注DNS解析耗时情况、运营商LocalDNS的劫持、DNS调度这些问题。
步骤二:创建连接
跟服务器建立连接,这里包括TCP三次握手、TLS密钥协商等工作。多个IP/端口该如何选择、是否要使用HTTPS、能否可以减少甚至省下创建连接的时间,这些问题都是我们优化的关键。
步骤三:发送/接收数据
在成功建立连接之后,就可以愉快地跟服务器交互,进行组装数据、发送数据、接收数据、解析数据。我们关注的是,如何根据网络状况将带宽利用好,怎样快速地侦测到网络延时,在弱网络下如何调整包大小等问题。
步骤四:关闭连接
连接的关闭看起来非常简单,其实这里的水也很深。这里主要关注主动关闭和被动关闭两种情况,一般我们都希望客户端可以主动关闭连接。
所谓网络优化,就是围绕速度、弱网络、安全这三个核心内容,减少每一个步骤的耗时,打造快速、稳定且安全的高质量网络。
大平台网络库的实现(网络库对比图)
问题:为什么大厂都不使用OkHttp呢?
原因:主要是因为它不支持跨平台,对于大型应用来说跨平台是非常重要的。我们不希望所有的优化Android和iOS都要各自去实现一套,不仅浪费人力而且还容易出现问题。
对于大厂来说,不能只局限在客户端网络库的双端统一上,网络优化不仅仅是客户端的事情,所以一般都有统一的网络中台,它负责提供前台一整套网络解决方案。
阿里的 ACCS、蚂蚁的 mPaas、携程的网络服务都是公司级的网络中台服务,这样所有的网络优化可以让整个集团的所有接入应用受益。
优化一:监听网络状态
根据网络状态对网络请求进行区别对待,2G与WiFi状态下网络质量肯定是不一样的,那对应的网络策略也应该是不一样的,策列包括:网络是否连接,网络连接类型,监听网络变化。
例如:1、在WiFi场景下可以进行数据的预取、一些统计的集中上传等。
2、而在2G场景下此类操作以及网络请求的次数策略都应该调低。
优化二:设置网络缓存
在一定时间内,对服务端返回的数据进行缓存,比如一些接口的数据不会更新(10分钟或更久变化一次),我们就可以缓存该接口的数据,设定有效时间,可以减少不必要的流量消耗。
Android系统上关于网络请求的Http Response Cache是默认关闭的,这样会导致每次即使请求的数据内容是一样的也会需要重复被调用执行,效率低下。
备注:如果全部自己从头开始写会比较繁琐复杂,有不少著名的开源框架Volley、Okhttp都很好的支持实现自定义缓存。
优化三:减小传输数据量
为了能够减小网络传输的数据量,我们需要对传输的数据做压缩的处理,这样能够提高网络操作的性能。首先不同的网络环境,下载速度以及网络延迟是存在差异的,
如下图所示:
总结:
如果我们选择在网速更低的网络环境下进行数据传输,这就意味着需要执行更长的时间,而更长的网络操作行为,会导致电量消耗更加严重。另外传输的数据如果不做压缩处理,也同样会增加网络传输的时间,消耗更多的电量。不仅如此,未经过压缩的数据,也会消耗更多的流量,使得用户需要付出更多的流量费。
通常来说,网络传输数据量的大小主要由两部分组成:图片与序列化的数据,那么我们需要做的就是减少这两部分的数据传输大小。
使用不同分辨率的图片:
首先需要做的是减少图片的大小,选择合适的图片保存格式是第一步。
下图展示了PNG、JPEG、WEBP三种主流格式在占用空间与图片质量之间的对比:
总结:对于JPEG与WEBP格式的图片,不同的清晰度对占用空间的大小也会产生很大的影响,适当的减少JPG质量,可以大大的缩小图片占用的空间大小。
另外,我们需要为不同的使用场景提供当前场景下最合适的图片大小,例如针对全屏显示的情况我们会需要一张清晰度比较高的图片,而如果只是显示为缩略图的形式,就只需要服务器提供一个相对清晰度低很多的图片即可。
服务器应该支持到为不同的使用场景分别准备多套清晰度不一样的图片,以便在对应的场景下能够获取到最适合自己的图片。这虽然会增加服务端的工作量,可是这个付出却十分值得!
压缩序列化数据:
减少序列化数据的大小,不直接使用JSON和XML格式数据。
JSON与XML为了提高可读性,在文件中加入了大量的符号,空格等等字符,而这些字符对于程序来说是没有任何意义的。我们应该使用ProtocalBuffers,Nano-Proto-Buffers,FlatBuffer来减小序列化的数据的大小。
Protocol Buffer是Google开发的一种数据交换的格式,它独立于语言,独立于平台。相较于目前常用的JSON,数据量更小,意味着传输速度也更快。
优化四:IP直连与DNS
DNS解析的失败率占联网失败中很大一种,而且首次域名解析一般需要几百毫秒,针对此,我们可以不用域名,采用IP直连省去DNS解析过程,节省这部分时间。
另外熟悉阿里云的小伙伴肯定知道HTTP DNS,HTTP DNS基于HTTP协议的域名解析,替代了基于DNS协议向运营商Local DNS发起解析请求的传统方式,可以避免Local DNS造成的域名劫持和跨网访问问题,解决域名解析异常带来的困扰。
优化五:文件下载与上传
文件、图片等的下载,采用断点续传,不浪费用户之前消耗过的流量。
文件的上传失败率比较高,不仅仅因为大文件,同时带宽、时延、稳定性等因素在此场景下的影响也更加明显。
一:避免整文件传输,采用分片传输。
二:根据网络类型以及传输过程中的变化动态的修改分片大小。
三:每个分片失败重传的机会。
优化六:HTTP协议优化
使用最新的协议,HTTP协议有多个版本:0.9、1.0、1.1、2等。
新版本的协议经过再次的优化,例如:HTTP 1.1版本引入了「持久连接」,多个请求被复用,无需重建TCP连接,而TCP连接在移动互联网的场景下成本很高,节省了时间与资源。
HTTP 2.0引入了「多工」、头信息压缩、服务器推送等特性。
新的版本不仅可以节省资源,同样可以减少流量。
优化七:请求打包
合并网络请求,减少请求次数。对于一些接口类如统计,无需实时上报,将统计信息保存在本地,然后根据策略统一上传。这样头信息仅需上传一次,减少了流量也节省了资源。
网络检测工具使用:
工具一:Network Profiler
Network Profiler是Android Profiler中的一个组件,Android Profiler可帮助开发者识别导致应用卡顿、OOM和内存泄露。它显示一个应用内存使用量的实时图表,可以捕获堆转储、强制执行垃圾回收以及跟踪内存分配,利用Network Profiler检查网络流量。
工具二:Charles、Fiddler
使用Charles、Fiddler等抓包工具同样可以实现Network Monitor的功能,而且更加强大。
工具三:Stetho
Stetho是Facebook出品的一个Android应用的调试工具。
无需Root即可通过Chrome,在Chrome Developer Tools中可视化查看应用布局、网络请求、SQLite,Preference等。同样集成了Stetho之后也可以很方便的查看网络请求的各种情况。
十八:扩展阅读
1、https://www.cnblogs.com/guolingyun/p/6148462.html(Android中XML的三种解析方式2、 https://blog.csdn.net/langtop/article/details/77972855(HttpClient、HttpURLConnection、OKHttp和Volley优缺点和性能对比,如何选择)
3、https://www.cnblogs.com/index-html/p/traffic-hijack.html(流量劫持是如何产生的)
4、https://server.zzidc.com/fwqcjwt/2557.html(如何防止中间人攻击)
5、 https://blog.csdn.net/sd19871122/article/details/79399441(Android4种网络连接方式HttpClient、HttpURLConnection、OKHttp和Volley优缺点和性能对比)
6、https://www.cnblogs.com/heluan/p/8620312.html( HTTP1.0、HTTP1.1 和 HTTP2.0 的区别)
7、https://www.jianshu.com/p/bb3eeb36b479( QUIC协议浅析与HTTP/3.0)
8、https://www.cnblogs.com/chenjinxinlove/p/10104854.html( HTTP3.0(QUIC的实现机制) )
9、https://www.jianshu.com/p/050c6db5af5a(Android开源:主流网络请求库对比(Android-Async-Http、Volley、OkHttp、Retrofit))
10、https://blog.csdn.net/u014756827/article/details/78870365(BIO与NIO、AIO的区别(这个容易理解))
11、https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode/blob/master/article/android/performance/05_network.md(网络性能优化那些事)
12、https://blog.csdn.net/qq_41727218/article/details/82461089(IP协议详解)