Spring 没有 SockJS/StompJS 的 STOMP 服务器

Spring STOMP server without SockJS/StompJS

我有 Spring 服务器,支持 Spring Websocket。我想使用 STOMP 子协议来处理网络套接字上的通信,因此 STOMP 端点的配置如下所示:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat")
                .setAllowedOrigins("*")
                .withSockJS();
    }
}

Spring 文档和基本上我能找到的关于该主题的任何资源都展示了如何使用 SockJS + StompJS 创建 STOMP 客户端。它可以工作,但据我所知,根本不需要它——因为 STOMP 只是一个子协议,我应该能够基本上通过使用 STOMP 消息语法从任何 Web 套接字客户端与我的服务器通信。

假设我只想从 Google Chrome Simple Web Socket Client 插件连接到我的 STOMP 服务器。根据 STOMP 规范,我做的第一件事就是打开网络套接字连接。我用

ws://my.server.here/chat/websocket

link。这部分有效,我的连接已建立。现在我想使用 STOMP。正如 STOMP 规范所说,我现在应该发送如下所示的 CONNECT 命令(STOMP 1.1):

CONNECT
accept-version:1.0,1.1
host:my.host.here

^@

然后我希望服务器用 CONNECTED 命令响应,但我什么也没得到。如果我将使用一些不存在的命令而不是 "CONNECT",例如 "WRONG_COMMAND",那么我可以看到 Spring 异常被抛出关于未知命令,所以我想我的消息命中 Spring的 Websocket 内部结构,但我无法取回任何东西。如果这可行,我想使用后续的 SEND、SUBSCRIBE 等命令来执行操作。

这种工作流程是否可行?我是在做错什么,还是我错误地理解了整个想法及其运作方式?

我已经解决了这个问题,所以简短的回答是 是的,您可以使用 Spring 的 STOMP 消息传递而不需要 SockJS,只需将适当的构造消息发送到网络套接字端点。

更长的答案是我无法使用 Google 简单 Websocket 客户端执行此操作,因为 STOMP 语法中的 ^@ 字符意味着,引用 STOM 文档:

examples in this document will use ^@, control-@ in ASCII, to represent the NULL octet.

Google 的 Websocket 客户端的问题是,正如我所想的那样,我真的无法用它发送这个空八位字节,所以我的 STOMP 消息没有正确终止。

我需要它来为无法使用 SockJS 的移动应用程序进行简单聊天,在我公司移动开发人员的帮助下,我们能够编写工作解决方案,它基本上只是一个与 STOMP 兼容的消息格式化程序 sub-protocol.

我们使用 Xamarin 和 C# 进行移动应用程序开发。连接到 STOMP 是这样完成的。请注意,我们首先打开与 websocket 的常规连接,并在建立后进入 STOMP 处理:

var connectString = String.Format("CONNECT\naccept-version:1.0,1.1\nlogin:{0}\nheart-beat:30000,0\n\n[=10=]", AuthService.TOKEN);
webSocketConnection = Websockets.WebSocketFactory.Create();
webSocketConnection.OnOpened += () => 
{
    webSocketConnection.Send(connectString);
    Debug.WriteLine("opened");
};

您必须使用客户端 onMessage 方法或等效方法处理来自服务器的响应。建立连接后,您可以像这样发送 STOMP 消息,例如我们在我们的应用程序中所做的那样:

var messageString = String.Format("SEND\ndestination:/app/chat/send/{0}\nlogin:{1}\n\n{{\"message\":\"{2}\"}}\n[=11=]", chatName, AuthService.TOKEN, message);
webSocketConnection.Send(messageString);

另请记住,您可能需要支持心跳,因此后端不会认为您的应用已死而断开连接。在我们的移动应用程序中,我们从另一个线程发送心跳。 Heartbeat 只是发送到 websocket 地址的换行消息。请注意,它不包含任何 STOMP headers 等:

webSocketConnection.Send("\n");

我们使用 this 作为我们的 websocket 客户端。

这只是我们在不使用 SockJS 的情况下完全支持与 Spring 的 Websockets 连接的基础,如果您有其他问题,请随时询问。感谢 Mateusz Gaffke 帮助和实施移动端。