首页 > 网络编程 > JavaScript > javascript类库 > vue.js > spring的websocket作为客户端接收数据时1009错误(非ServletServerContainer)
快速解决spring的websocket作为客户端接收数据时1009错误(非ServletServerContainer问题)
作者:嚯呀怪怪怪
Spring Boot WebSocket客户端因缓冲区过小导致连接断开(错误1009),正确解决方案是通过WebSocketContainer自定义缓冲区大小和过期时间,而非配置类,需在创建StandardWebSocketClient时传入预设的container实例
项目场景
使用springboot自带的websocket库作为客户端向设备进行连接获取设备推送的数据,包括纯数据以及携带base64图片的数据
问题描述
WebSocket接收数据时连接断开
报错1009 The decoded text message was too big for the output buffer and the endpoint does not support partial messages
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 处理接收到的消息
logger.info("Received message from device: " + message.getPayload());
}
原因分析
WebSocket缓冲区过小,装不下数据
需要给websocket缓冲区扩容,但是问题就在于全网查询后,包括StackOverflow及ChatGPT的回答都聚焦于两个点
- 一个是修改tomocat的缓冲区,在jar包启动时加上如下启动命令
-Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=327680
- 一个是写Config类
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
// 在此处设置bufferSize
container.setMaxTextMessageBufferSize(512000);
container.setMaxBinaryMessageBufferSize(512000);
container.setMaxSessionIdleTimeout(15 * 60000L);
return container;
}
}
问题也就在这里
这个配置文件并不能解决实际的缓冲区大小,但确实是对的思路。
解决方案
首先我们查看连接所使用的类的源码
正常通过StandardWebSocketClient client = new StandardWebSocketClient();进行创建一个连接的client,使用默认的配置。但是StandardWebSocketClient是可以构造一个container传入的
public StandardWebSocketClient(WebSocketContainer webSocketContainer) {
Assert.notNull(webSocketContainer, "WebSocketContainer must not be null");
this.webSocketContainer = webSocketContainer;
}
继续查看WebSocketContainer 的源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package javax.websocket;
import java.io.IOException;
import java.net.URI;
import java.util.Set;
public interface WebSocketContainer {
long getDefaultAsyncSendTimeout();
void setAsyncSendTimeout(long var1);
Session connectToServer(Object var1, URI var2) throws DeploymentException, IOException;
Session connectToServer(Class<?> var1, URI var2) throws DeploymentException, IOException;
Session connectToServer(Endpoint var1, ClientEndpointConfig var2, URI var3) throws DeploymentException, IOException;
Session connectToServer(Class<? extends Endpoint> var1, ClientEndpointConfig var2, URI var3) throws DeploymentException, IOException;
long getDefaultMaxSessionIdleTimeout();
void setDefaultMaxSessionIdleTimeout(long var1);
int getDefaultMaxBinaryMessageBufferSize();
void setDefaultMaxBinaryMessageBufferSize(int var1);
int getDefaultMaxTextMessageBufferSize();
void setDefaultMaxTextMessageBufferSize(int var1);
Set<Extension> getInstalledExtensions();
}
问题的关键就在这里!set方法告诉我们WebSocketContainer 是可以设置缓冲区大小的
因此解决方案就出来了
在新建客户端连接的时候,构造好container传入就可以自定义缓冲区大小和过期时间了,代码如下
WebSocketContainer container = new WsWebSocketContainer(); // 设置二进制消息缓冲区大小(以字节为单位) container.setDefaultMaxBinaryMessageBufferSize(5120000); // 设置文本消息缓冲区大小(以字节为单位) container.setDefaultMaxTextMessageBufferSize(5120000); // 设置会话空闲超时时间(以毫秒为单位) container.setDefaultMaxSessionIdleTimeout(15 * 60000L); StandardWebSocketClient client = new StandardWebSocketClient(container);
大功告成!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
