解决spring的websocket作为客户端接收数据时1009错误(非ServletServerContainer问题)

项目场景:

使用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);

大功告成!

  • 20
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值