vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > 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的回答都聚焦于两个点

-Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=327680
@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);

大功告成!

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文