Можно ли отправлять двоичные данные с помощью STOMP через WebSockets, используя Spring-WebSockets?

Я могу отправлять и получать JSON с помощью STOMP через WebSockets, следуя весенняя документация. Однако при больших скоростях производительность низкая, поэтому я хочу профилировать использование двоичных сообщений.

  • Spring-веб-сокеты 4.0
  • Клиент JavaScript, работающий в Chrome 35
  • 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

Вещи, которые я пробовал

Я понимаю, что T в STOMP означает текст, однако документация Spring подразумевает, что двоичные сообщения возможны, по крайней мере, с помощью простых веб-сокетов, а также спецификация топать указывает

STOMP основан на тексте, но также позволяет передавать двоичные сообщения.

  • Отладка кода отправки, и, насколько я вижу, он остается как байт []
  • Отладка библиотеки stomp.js во время получения. Сообщение выглядит как строка при получении в базовом обратном вызове ws.onmessage (строка 243 в stomp-1.7.1.js).
  • Много поиска - это кажется редкой темой с небольшим количеством информации.
  • Глядя на исходный код 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)));
}

Мой вопрос

  • Возможен ли такой подход при таком сочетании технологий?
  • Я пропустил какой-то важный шаг?
  • Может ли кто-нибудь указать мне рабочий пример

person Adam    schedule 06.10.2014    source источник
comment
Можете ли вы опубликовать заголовки кадров Stomp?   -  person mjn    schedule 20.10.2014
comment
Какой брокер сообщений?   -  person mjn    schedule 20.10.2014


Ответы (2)


Кажется, что 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 для отправки двоичных сообщений.
person Adam    schedule 03.11.2014
comment
Есть ли у нас все еще такое же решение для отправки двоичных данных с использованием stomp через веб-сокет (без sockjs)? - person UserBSS1; 06.05.2020

Попробуйте настроить свой сервер только с помощью 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.

person Artem Bilan    schedule 06.10.2014
comment
спасибо за предложение. Я пробовал это, но это не решает проблему. Я его отладил, класс конфига создан и вызывается configureMessageConverters. Я пытался сделать перерывы в ByteArrayMessageConverter.supports, convertFromInternal и convertToInternal, но ни один из этих методов не вызывается, хотя ему все еще удается отправить клиенту! - да, я определенно в режиме отладки. - person Adam; 06.10.2014
comment
Добавил больше информации в ответ - person Artem Bilan; 06.10.2014
comment
Из спецификации STOMP: STOMP основан на тексте, но также позволяет передавать бинарных сообщений. - за заголовком могут следовать двоичные данные, в этом случае заголовок должен указывать длину содержимого. (JSON не упоминается в официальной спецификации на github) - person mjn; 20.10.2014