WebSocketClient objects are not reuseable
You cannot initialize a reconnect out of the websocket thread. Use reconnect in another thread to insure a successful cleanup.
今天主要解决如上这两个问题。
使用的java-websocket版本是1.5.1
参考的文章:
关于WebSocket的 WebSocketClient objects are not reuseable
使用WebSocket实现Android端即时通讯聊天功能
上面两篇文章把引发问题的原因描述的比较清楚了,但是还是可以做补充说明。
我报上面这两个错的原因是在onclose中调用了connect与reconnect。
先说解决方法,在onClose中不要使用connect与reconnect,在其他线程中使用connect与reconnect,也就是除了监听onClose事件的线程,任何代码块中调用都是可以正常连接或重连的。
个人的方案是通过重写send方法,在send前检查连接状态来判断是否需要重连。
@Override
public void send(String text) {
boolean open = isConnectOpen();
if (open) {
super.send(text);
}
}
/**
* 在连接断开时尝试重连
*
* @return
*/
public boolean isConnectOpen() {
int t = 0;
if (null == this) {
return false;
}
// 连接断开
while (!this.isOpen()) {
try {
log.info("重连服务器...");
if (this.getReadyState().equals(ReadyState.NOT_YET_CONNECTED)) {
super.connectBlocking();
return true;
} else if (this.getReadyState().equals(ReadyState.CLOSING) || this.getReadyState().equals(ReadyState.CLOSED)) {
super.reconnectBlocking();
return true;
}
} catch (Exception e) {
log.error("reconnect error ", e);
}
}
return true;
}
现在分析具体代码
问题一: WebSocketClient objects are not reuseable
如上图,抛出这个异常时,表示当前连接已经被初始化过了(调用过connect方法),connectReadThread已经被初始化过了。
而当websocketclient对象初始化时(下图),不建立连接,直到调用connect方法时,才为connectReadThread初始化。
问题二:You cannot initialize a reconnect out of the websocket thread. Use reconnect in another thread to insure a successful cleanup.
先看reconnect代码
然后看reset代码,发现要将读取线程和写出线程都完全关闭。
这里可以看出来,当前执行reconnect的线程如果就是writeThread或者connectReadThread,会抛出这个异常。
原因是,第一张图中的代码:
connectReadThread = new Thread( this );
而connectReadThread执行的代码是:
发现connectReadThread会阻塞在这里,等待连接中的消息。
writeThread同理,会读取写出队列。
但是由于在onClose前,writeThread已经关闭了,所以reset时已经为null了。
综上所述,如果读取线程和写出线程就是当前执行reset的线程,就不能正常关闭,也就不能reset了。
而在项目中主线程中执行则可以正常使用。
由connectReadThread与writeThread引起的问题就这样解决了。