基于okhttp和RxJava封装的自动重连的WebSocket 原创 精华
目录
一. 概述
- RxWebSocket是一个基于okhttp和RxJava封装的WebSocket客户端,此库的核心特点是 除了手动关闭WebSocket(就是RxJava取消订阅),WebSocket在异常关闭的时候(onFailure,发生异常,如WebSocketException等等),会自动重连,永不断连.其次,对WebSocket做的缓存处理,同一个URL,共享一个WebSocket.
- 由于是基于RxJava封装,所以带来了无限可能,可以和RxBinding,Rxlifecycle一起使用,方便对WebSocket的管理.
效果图
项目已经上传Jcenter,依赖方法:
二. 使用方法
0.初始化,可以也忽略直接使用.
如果你想使用自己的okhttpClient:
是否打印日志:
1.获取一个WebSocket,接收消息,多种方式:
2.发送消息:
3.关闭WebSocket:
项目是依托RxJava实现的,所以关闭WebSocket的方法也就是在适当的时候注销 Observable,项目里的demo里,写了一个简单的lifecycle,将Observable生命绑定到Activity的onDestroy,自动注销.代码细节请看demo,因为内部实现了同一个URL的WebSocket共享机制,所以当外部所有持有这个URL的Observable都注销后,这个WebSocket连接就会自动关闭.请看原理解析部
三. 原理解析
1. 首先需要将okhttp的WebSocket包装成Observable,由于需要将WebSocket,Stringmsg,ByteString等信息一同发送给观察者所以先构建一个WebSocketInfo类,将信息封装:
onOpen字段主要用来判断当前的这个WebSocketInfo是否是当WebSocket打开时发送的消息(onOpen),这时,Stringmsg和ByteString都是null.
2. 将WebSocketInfo包装成Observable发出:
实现一个WebSocketOnSubscribe 将WebSocket的回调转化成subscriber调用.发送给Observable下游.在onOpen时调用 subscriber.onStart(),并且发送一个onOpen的WebSocketInfo.在subscriber注销的时候关闭WebSocket.在call方法最上面有个SystemClock.sleep(2000),这个主要是为了降低在断连的时候的重连频率,将在下面讲到.
包装成Observable:
3. 实现自动重连:
RxJava retry操作符,很完美的实现了这个功能,当上游发出Throwable的时候,retry将错误吃掉,并重新调用 onSubscribe的call方法,也就是WebSocketOnSubscribe的call,就会重新初始化一个WebSocket连接,达到重连的目的,如果一直没有网络,这个retry的调用频率非常高,所以在call方法里面,当是重连的时候,就SystemClock.sleep(2000),休眠2秒,这样重连的频率就是2秒重连一次. 当然在retry上面还有一个timeout操作符.当subscriber.onNext()在指定时间间隔里没有调用,就发出一个timeoutException,让retry重连WebSocket.这个主要是为了适配部分国产机型,当WebSocket发生连接异常时,不会及时发出错误,如小米平板.在每次重连都会把原来的WebSocket关闭.
4. 实现同一个URL的WebSocket共享
实现共享功能,主要是为了防止一个URL的WebSocket,建立多个连接,这个主要是由RxJava的share操作符实现,share操作符,使得一个Observable可以有多个subscriber,当有多个subscriber时,当所有的subscriber都取消订阅,这个Observable才会取消订阅.
getWebSocketInfo()方法完整代码:
doOnUnsubscribe作用:在Observable注销,即 WebSocket关闭时,移除map中的缓存的Observable和WebSocket.
doOnNext作用: 判断接收到的WebSocketInfo是否是WebSocket在onOpen的时候发的,然后将其缓存起来.作用就是:如果有一个相同的URL订阅Observable,就从缓存中取,这个时候我们应该把一个WebSocket的onOpen事件也发给这个订阅者:
这样的话,同一个URL的WebSocket,不管在什么地方什么时间订阅,都能收到一个onOpen事件,外部表现的就像一个新的WebSocket.
getWebSocketInfo方法的几种变体:
5 . send信息到服务端
上面已经讲到WebSocketInfo包含了WebSocket,所以在订阅后,就可以拿到这个WebSocket引用就可以WebSocket.send发送消息到服务端.当然我们的RxWebSocketUtil已经将开启的WebSocket已经缓存.所以我们也可以这样发消息:
当指定的URL的WebSocket没有打开会直接报错.
异步发送消息到服务端
这两种发送方式,你不用关心URL的WebSocket是否打开,可以直接发送.实现思路也很简单,getWebSocket(url)会获取到Observable,或者是从缓存中取,或者是重新开启一个WebSocket,但你都不需要关心,经过first操作符后,如果是从缓存取的Observable,就注销的当前的Observable,当是新开的WebSocket,注销掉当前的subscriber后,就没有其他subscriber了,这个新开的WebSocket就会关闭(share操作符作用).
最后,如有什么好的建议,可以联系我.
项目地址: gitee
优秀的websocket客户端
依赖编译通不过