В качестве конечной точки сервера msg-push я использую websocket с пружинным штампом.Когда я использую веб-браузер для подключения к нему, браузер и сервер работают хорошо.Но недавно, когда я использую симулятор приложения Cocos для подключения к своему серверу, он всегда не может подключиться правильно.На сервере нет сообщения об ошибке и запроса от клиента.При отладке я обнаружил, что запрос соединения симулятора может быть перехвачен только перехватчиком рукопожатия, но не в ClientInboundChannelInterceptor.
После некоторых исследований я обнаружил некоторые журналы ошибок на уровне TRACE, как показано ниже:
2019-03-01 11:34:09.433 INFO [msg-push,76064c86f7a1571f,76064c86f7a1571f,true] 5300 --- [nio-9006-exec-1] c.x.m.s.i.ClientHandshakeInterceptor : before handshake --> http://172.18.3.39:9005/stomp-ws
2019-03-01 11:34:09.456 INFO [msg-push,76064c86f7a1571f,76064c86f7a1571f,true] 5300 --- [nio-9006-exec-1] c.x.m.s.i.ClientHandshakeInterceptor : after handshake --> websocket
2019-03-01 11:34:09.487 TRACE [msg-push,,,] 5300 --- [nio-9006-exec-1] o.s.messaging.simp.stomp.StompDecoder : Incomplete frame, resetting input buffer...
2019-03-01 11:34:09.487 TRACE [msg-push,,,] 5300 --- [nio-9006-exec-1] o.s.w.s.m.StompSubProtocolHandler : Incomplete STOMP frame content received in session StandardWebSocketSession[id=0, uri=/stomp-ws], bufferSize=95, bufferSizeLimit=65536.
Кажется, что есть какая-то проблема с методом декодирования класса org.spring framework.messaging.simp.stomp.StompDecoder
.Код для метода выглядит следующим образом:
/**
* Decode a single STOMP frame from the given {@code buffer} into a {@link Message}.
*/
@Nullable
private Message<byte[]> decodeMessage(ByteBuffer byteBuffer, @Nullable MultiValueMap<String, String> headers) {
Message<byte[]> decodedMessage = null;
skipLeadingEol(byteBuffer);
// Explicit mark/reset access via Buffer base type for compatibility
// with covariant return type on JDK 9's ByteBuffer...
Buffer buffer = byteBuffer;
buffer.mark();
String command = readCommand(byteBuffer);
if (command.length() > 0) {
StompHeaderAccessor headerAccessor = null;
byte[] payload = null;
if (byteBuffer.remaining() > 0) {
StompCommand stompCommand = StompCommand.valueOf(command);
headerAccessor = StompHeaderAccessor.create(stompCommand);
initHeaders(headerAccessor);
readHeaders(byteBuffer, headerAccessor);
payload = readPayload(byteBuffer, headerAccessor);
}
if (payload != null) {
if (payload.length > 0) {
StompCommand stompCommand = headerAccessor.getCommand();
if (stompCommand != null && !stompCommand.isBodyAllowed()) {
throw new StompConversionException(stompCommand +
" shouldn't have a payload: length=" + payload.length + ", headers=" + headers);
}
}
headerAccessor.updateSimpMessageHeadersFromStompHeaders();
headerAccessor.setLeaveMutable(true);
decodedMessage = MessageBuilder.createMessage(payload, headerAccessor.getMessageHeaders());
if (logger.isTraceEnabled()) {
logger.trace("Decoded " + headerAccessor.getDetailedLogMessage(payload));
}
}
else {
logger.trace("Incomplete frame, resetting input buffer...");
if (headers != null && headerAccessor != null) {
String name = NativeMessageHeaderAccessor.NATIVE_HEADERS;
@SuppressWarnings("unchecked")
MultiValueMap<String, String> map = (MultiValueMap<String, String>) headerAccessor.getHeader(name);
if (map != null) {
headers.putAll(map);
}
}
buffer.reset();
}
}
else {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.createForHeartbeat();
initHeaders(headerAccessor);
headerAccessor.setLeaveMutable(true);
decodedMessage = MessageBuilder.createMessage(HEARTBEAT_PAYLOAD, headerAccessor.getMessageHeaders());
if (logger.isTraceEnabled()) {
logger.trace("Decoded " + headerAccessor.getDetailedLogMessage(null));
}
}
return decodedMessage;
}
мы можем видеть, если полезная нагрузка == ноль, то в журналах ошибок происходит:
logger.trace("Incomplete frame, resetting input buffer...");
Приведенная выше ситуация вызовет сообщениекадр не будет правильно обработан, полученный методом: org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient()
.Поскольку код messages = decoder.decode(byteBuffer);
вернет пустой список, я получил журнал Incomplete STOMP frame content ...
Часть кода выглядит следующим образом:
List<Message<byte[]>> messages;
try {
ByteBuffer byteBuffer;
if (webSocketMessage instanceof TextMessage) {
byteBuffer = ByteBuffer.wrap(((TextMessage) webSocketMessage).asBytes());
}
else if (webSocketMessage instanceof BinaryMessage) {
byteBuffer = ((BinaryMessage) webSocketMessage).getPayload();
}
else {
return;
}
BufferingStompDecoder decoder = this.decoders.get(session.getId());
if (decoder == null) {
throw new IllegalStateException("No decoder for session id '" + session.getId() + "'");
}
messages = decoder.decode(byteBuffer);
if (messages.isEmpty()) {
if (logger.isTraceEnabled()) {
logger.trace("Incomplete STOMP frame content received in session " +
session + ", bufferSize=" + decoder.getBufferSize() +
", bufferSizeLimit=" + decoder.getBufferSizeLimit() + ".");
}
return;
}
}
Я не знаю, почемуфрейм сообщения будет расшифрован до нуля, кто мне может помочь?
Дополнение:
Код клиентского подключения, подобный этому:
var client = Stomp.client("ws://172.18.3.39:9005/msgpush/stomp-ws/");
var headers = {
login: 'mylogin',
passcode: 'mypasscode',
};
client.connect(headers, connectCallback);
Среда разработки:
springboot 2.0.3.RELEASE