使用java-websocket框架开发websocket客户端时遇到的两个问题

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引起的问题就这样解决了。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Spring框架中,您可以使用两个不同的启动类来配置WebSocket:`WebSocketMessageBrokerConfigurer`和`WebSocketConfigurer`。 1. `WebSocketMessageBrokerConfigurer`:这个启动类用于配置基于消息代理的WebSocket。它提供了一种更高级的配置方式,可以实现基于消息代理的广播、点对点消息等功能。 ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); // 配置消息代理,可以用于订阅广播消息的客户端 config.setApplicationDestinationPrefixes("/app"); // 配置应用程序前缀,用于定义请求的目的地 } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); // 注册STOMP协议的WebSocket端点 } } ``` 上述配置类使用了`@EnableWebSocketMessageBroker`注解来启用WebSocket消息代理功能。`configureMessageBroker`方法用于配置消息代理,其中`enableSimpleBroker`方法用于配置简单的消息代理,允许客户端订阅以`/topic`开头的目的地。`setApplicationDestinationPrefixes`方法用于设置应用程序前缀,客户端发送的请求目的地需要以该前缀开始。 `registerStompEndpoints`方法用于注册STOMP协议的WebSocket端点。在上述例子中,注册了一个名为`/ws`的端点,并启用了SockJS子协议,以便支持在不支持WebSocket的浏览器上进行通信。 2. `WebSocketConfigurer`:这个启动类用于配置基本的WebSocket连接。它提供了一种更简单的方式来配置WebSocket,但不支持消息代理功能。 ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/ws").setAllowedOrigins("*"); // 注册WebSocket处理程序 } @Bean public WebSocketHandler myHandler() { return new MyHandler(); } } ``` 上述配置类使用了`@EnableWebSocket`注解来启用WebSocket功能。`registerWebSocketHandlers`方法用于注册WebSocket处理程序,其中`myHandler`方法返回一个自定义的WebSocket处理程序。在上述例子中,注册了一个名为`/ws`的处理程序,并允许来自任何来源的连接。 注意:您可以根据您的需求选择适合的启动类来配置WebSocket。如果您需要更高级的功能,如消息代理、广播等,可以使用`WebSocketMessageBrokerConfigurer`。如果您只需要基本的WebSocket连接,可以使用`WebSocketConfigurer`。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值