是否可以使用Spring WebSockets通过WebSockets发送STOMP二进制数据

Is it possible to send binary data with STOMP over WebSockets using Spring-WebSockets?

本文关键字:WebSockets STOMP 二进制 数据 发送 通过 Spring 是否 可以使      更新时间:2023-09-26

我能够在spring文档之后通过WebSockets通过STOMP发送和接收JSON。然而,在高速率较高的情况下,性能较差,因此我希望简要介绍二进制消息的使用。

  • Spring WebSockets 4.0
  • Chrome 35中运行的JavaScript客户端
  • stomp.js 1.7.1

正在发送

我使用SimpMessageTemplate和必要的代理中继发送消息-请参阅春季文档

@Controller
public class DemoBinaryController {
   @Autowired
   private SimpMessagingtemplate template
   @Scheduled(fixedDelay = 5000)
   public void demo() throws Exception {
      GenericMessage<byte[]> message = new GenericMessage<byte[]>(new byte[]{65,66,67});
      template.send("/app/binarydemo", message);
   }
}

接收

JavaScript客户端使用标准机制使用stomp.js接收数据。

var subscription = client.subscribe("/app/binarydemo", new function(message) {
   console.log("RX message", typeof message.body, message.body.length);
});

消息被接收,但作为字符串,控制台输出如下。我期待一些原始类型,比如ArrayBuffer

RX message string  3
RX message string  3

我尝试过的东西

我意识到STOMP中的T代表文本,然而Spring文档暗示二进制消息是可能的,至少在普通WebSockets中是这样,STOMP规范也声明

STOMP是基于文本的,但也允许传输二进制消息。

  • 调试发送代码,在我所能看到的范围内,它似乎保持为byte[]
  • 接收时调试stomp.js库。当在底层的ws.onmessage回调(stomp-1.7.1.js中的第243行)中接收到消息时,该消息显示为String
  • 大量搜索-这似乎是一个信息很少的罕见话题
  • 查看stomp.js源代码。对二进制文件的唯一引用是ws.binaryType="arraybuffer"

更新:我在服务器端做了更多的调试。org.springframework.web.socket.TextMessage似乎总是在org.springfframework.web.socket.messaging.SstompSubProtocolHandler中使用,而不是在org.springframework.web.socket.BinaryMessage中使用。我已经对此SPR-12301 提出了功能请求

message = MessageBuilder.withPayload(message.getPayload()).setHeaders(headers).build();
byte[] bytes = this.stompEncoder.encode((Message<byte[]>) message);
synchronized(session) {
    session.sendMessage(new TextMessage(new String(bytes, UTF8_CHARSET)));
}

我的问题

  • 这种混合技术的方法可行吗
  • 我是不是错过了关键的一步
  • 有人能给我举个例子吗

org.springframework.web.socket.TextMessage似乎总是在org.springfframework.web.socket.messaging.SstompSubProtocolHandler中使用,而不是在org.springframework.web.socket.BinaryMessage中使用。我已经为此SPR-12301提出了一个功能请求,该请求已被接受。

message = MessageBuilder.withPayload(message.getPayload()).setHeaders(headers).build();
byte[] bytes = this.stompEncoder.encode((Message<byte[]>) message);
synchronized(session) {
    session.sendMessage(new TextMessage(new String(bytes, UTF8_CHARSET)));
}

更新

  • SPR-12301在4.1.2中交付,但仅增加了对接收二进制消息的支持
  • 用于发送二进制消息的引发SPR-12475

尝试仅使用ByteArrayMessageConverter:配置服务器

@Configuration
@EnableWebSocketMessageBroker
public class MyWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
   
   @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        messageConverters.add(new ByteArrayMessageConverter());
        return false;
    }
}

更新

啊!我明白了。谢谢:

public TextMessage(byte[] payload) {
    super(new String(payload, UTF_8));
    this.bytes = payload;
}

来自STOMP规范的另一侧:

STOMP消息的正文必须是字符串。如果您想发送和接收JSON对象。。。

根据ArrayBuffer:

从现有数据中获取阵列缓冲区

  • 从Base64字符串
  • 从本地文件

所以,我认为你没有chioce,而不是为你提供一些自定义的MessageConverter,它将你的byte[]转换为Base64字符串并发送它。

在JavaScript方面,您应该以某种方式将该字符串解码为ArrayBuffer