没有 SockJS/StompJS 的 Spring STOMP 服务器

Ple*_*usz 5 java stomp spring-websocket

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

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

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

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

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

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

关联。这部分工作,我的连接建立。现在我想使用STOMP。再次正如 STOMP 规范所说,我现在应该发送如下所示的 CONNECT 命令(STOMP 1.1):

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

^@
Run Code Online (Sandbox Code Playgroud)

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

这种工作流程甚至可能吗?我做错了什么,或者我错误地理解了整个想法及其运作方式?

Ple*_*usz 5

我已经解决了这个问题,所以简短的回答是肯定的,您可以在没有 SockJS 的情况下使用 Spring 的 STOMP 消息传递,只需将适当的构造消息发送到 websocket 端点即可。

更长的答案是我无法使用 Google Simple Websocket Client 做到这一点,因为^@STOMP 语法中的字符意味着,引用 STOM 文档:

本文档中的示例将使用 ASCII 中的 ^@、control-@ 来表示 NULL 八位字节。

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

我需要它用于无法使用 SockJS 的移动应用程序的简单聊天,并且在我公司移动开发人员的帮助下,我们能够编写工作解决方案,这基本上只是一个与 STOMP 子协议兼容的消息格式化程序。

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

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

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

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

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

webSocketConnection.Send("\n");
Run Code Online (Sandbox Code Playgroud)

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

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