【问题标题】:Is it possible to send binary data with STOMP over WebSockets using Spring-WebSockets?是否可以使用 Spring-WebSockets 通过 WebSockets 通过 STOMP 发送二进制数据?
【发布时间】:2014-11-30 13:41:25
【问题描述】:

我可以在spring documentation 之后通过 WebSockets 使用 STOMP 发送和接收 JSON。然而,在高速率下性能很差,所以我想分析一下二进制消息的使用。

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

发送中

我使用 SimpMessageTemplate 和必要的代理中继发送消息 - 请参阅 spring documentation

@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 代表 Text,但是 Spring 文档暗示二进制消息至少可以使用普通 WebSockets,stomp specification 状态也是可能的

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

  • 调试发送代码,据我所知,它似乎保持为字节 []
  • 在接收时调试 stomp.js 库。在底层 ws.onmessage 回调(stomp-1.7.1.js 中的第 243 行)中收到消息时,该消息似乎是一个字符串
  • 大量搜索 - 这似乎是一个信息很少的罕见主题
  • 查看 stomp.js 源代码。对二进制的唯一引用是 ws.binaryType = "arraybuffer"。

更新:我在服务器端做了更多的调试。似乎 org.springframework.web.socket.TextMessage 总是在org.springframework.web.socket.messaging.StompSubProtocolHandler 中使用,而不是 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)));
}

我的问题

  • 这种技术组合是否可行?
  • 我是否遗漏了一些关键步骤?
  • 谁能指点我一个工作示例

【问题讨论】:

  • 你能发布 Stomp 框架标题吗?
  • 是哪个消息代理?

标签: javascript spring websocket stomp spring-websocket


【解决方案1】:

似乎 org.springframework.web.socket.TextMessage 总是在 org.springframework.web.socket.messaging.StompSubProtocolHandler 而不是 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 用于发送二进制消息

【讨论】:

  • 我们是否还有上述相同的解决方案来使用 stomp over websocket(不带 sockjs)发送二进制数据?
【解决方案2】:

尝试使用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 字符串
  • 来自本地文件

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

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

【讨论】:

  • 感谢您的建议。我已经尝试过了,但它不能解决问题。我已经对其进行了调试,创建了配置类并调用了 configureMessageConverters。我已经尝试在 ByteArrayMessageConverter.supports、convertFromInternal 和 convertToInternal 上设置中断,但是这些方法都没有被调用,即使它仍然能够发送到客户端! - 是的,我肯定处于调试模式。
  • 在答案中添加了更多信息
  • 来自STOMP spec:“STOMP 是基于文本的,但也允许传输二进制消息。” - 标头后面可以跟二进制数据,在这种情况下,标头必须指定内容长度。 (github官方规范中没有提到JSON)
猜你喜欢
  • 2012-11-16
  • 2012-12-05
  • 2012-11-02
  • 2013-09-18
  • 2012-10-06
  • 2020-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多