简体   繁体   English

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

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

I am able to send and receive JSON with STOMP over WebSockets following spring documentation . 我可以在Spring文档之后通过WebSockets发送和接收带有STOMP的JSON。 However performance is poor at large high rates, so I wish to profile the use of binary messages. 然而,在高速率下性能很差,因此我希望分析二进制消息的使用。

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

Sending 发出

I send messages using SimpMessageTemplate with the necessary broker relay - see spring documentation 我使用SimpMessageTemplate发送消息和必要的代理中继 - 请参阅spring文档

@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);
   }
}

Receiving 接收

A JavaScript client receives data using stomp.js using the standard mechanism. JavaScript客户端使用标准机制使用stomp.js接收数据。

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

Messages are received, but as Strings, with console output as follows. 收到消息,但作为字符串,控制台输出如下。 I'm expecting some raw type, like ArrayBuffer 我期待一些原始类型,比如ArrayBuffer

RX message string  3
RX message string  3

Things I've tried 我尝试过的事情

I realise the T in STOMP stands for Text, however the Spring documentation implies binary messages are possible at least with plain WebSockets, also the stomp specification states 我意识到STOMP中的T代表Text,但是Spring文档意味着二进制消息至少可以使用普通的WebSockets,而且stomp规范也是如此。

STOMP is text based but also allows for the transmission of binary messages. STOMP是基于文本的,但也允许传输二进制消息。

  • Debugging the sending code, and it appears to remain as byte [] for as far as I can see 调试发送代码,就我所见,它似乎保持为byte []
  • Debugging the stomp.js library whilst receiving. 在接收时调试stomp.js库。 The message appears to be a String when received in the underlying ws.onmessage callback (line 243 in stomp-1.7.1.js) 在底层ws.onmessage回调中收到该消息似乎是一个字符串(stomp-1.7.1.js中的第243行)
  • Lots of searching - this seems a rare topic with little information 大量的搜索 - 这似乎是一个罕见的主题,几乎没有信息
  • Looking at the stomp.js source code. 看一下stomp.js的源代码。 The only reference to binary is ws.binaryType = "arraybuffer". 对二进制的唯一引用是ws.binaryType =“arraybuffer”。

Update: I've done more debugging on the server side. 更新:我在服务器端做了更多的调试。 It seems that org.springframework.web.socket.TextMessage is always used within org.springframework.web.socket.messaging.StompSubProtocolHandler rather than org.springframework.web.socket.BinaryMessage. 看来org.springframework.web.socket.TextMessage总是在org.springframework.web.socket.messaging.StompSubProtocolHandler而不是org.springframework.web.socket.BinaryMessage中使用。 I've raised a feature request for this SPR-12301 我已经提出了这个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)));
}

My question 我的问题

  • Is this approach possible with this mix of technologies? 这种混合技术可以采用这种方法吗?
  • Am I missing some crucial step? 我错过了一些关键步骤吗?
  • Can anyone point me to a working example 任何人都可以向我指出一个有效的例子

It seems that org.springframework.web.socket.TextMessage is always used within org.springframework.web.socket.messaging.StompSubProtocolHandler rather than org.springframework.web.socket.BinaryMessage. 看来org.springframework.web.socket.TextMessage总是在org.springframework.web.socket.messaging.StompSubProtocolHandler而不是org.springframework.web.socket.BinaryMessage中使用。 I've raised a feature request for this SPR-12301 which has been accepted. 我已经提出了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)));
}

Update 更新

  • SPR-12301 was delivered in 4.1.2 but only adds support for receiving binary messages SPR-12301在4.1.2中提供,但仅添加了对接收二进制消息的支持
  • Raised SPR-12475 for sending of binary messages 引发SPR-12475发送二进制消息

Try to configure you Server just with ByteArrayMessageConverter : 尝试使用ByteArrayMessageConverter配置服务器:

@Configuration
@EnableWebSocketMessageBroker
public class MyWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

   @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        messageConverters.add(new ByteArrayMessageConverter());
        return false;
    }

}

UPDATE UPDATE

Ah! 啊! I see that. 我看到。 Thanks: 谢谢:

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

From other side from STOMP spec: 来自STOMP规范的另一面:

The body of a STOMP message must be a String. STOMP消息的主体必须是String。 If you want to send and receive JSON objects, ... 如果要发送和接收JSON对象,...

According to the ArrayBuffer : 根据ArrayBuffer

Getting an array buffer from existing data 从现有数据中获取数组缓冲区

  • From a Base64 string 从Base64字符串
  • From a local file 从本地文件

So, I think you don't have a chioce rather than provide you some custom MessageConverter , which converts your byte[] to Base64 String and send it. 所以,我认为你没有chioce而不是为你提供一些自定义MessageConverter ,它将你的byte[]转换为Base64字符串并发送它。

On the JavaScript side you should decode that string to the ArrayBuffer somehow. 在JavaScript方面,您应该以某种方式将该字符串解码为ArrayBuffer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM