SockJS Python客户端

13

我有一个网站(Java + Spring),依赖于Websockets (Stomp over Websockets 用于Spring + RabbitMQ + SockJS) 的一些功能。

我们正在使用Python创建基于命令行的接口,并希望添加一些已经可用的websocket功能。

有没有人知道如何使用Python客户端,以便我可以使用SockJS协议进行连接?

PS_ 我知道一个简单的库,但我没有测试它,它没有订阅主题的能力

PS2_ 我可以直接连接到RabbitMQ中的STOMP并订阅主题,但是直接暴露RabbitMQ感觉不太对。对于第二个选项有任何评论吗?


你最终做了什么? - Jeef
@Jeef,我们找不到好的解决方案,所以我们不得不通过另一个API来模拟功能。 - Tk421
@Tk421 我们遇到了连接Python客户端到SockJS + Spring的相同问题。我们尝试在Python中使用websocket库。例如,ws = websocket.WebSocketApp("ws://localhost:8080/socket_name/topic_name/1/websocket"。我们能够连接到WebSocket,但无法接收发送到主题的消息。我们需要在Spring中添加任何自定义握手处理程序来实现这一点吗? - Raja Vikram
@RajaVikram,我已经发布了一个有效的示例作为回答,展示了我如何使用Python客户端与Spring Websockets服务器通信,并结合Stomp协议使用Websockets。希望它有所帮助。 - Michael
2个回答

5

我的解决方案是不使用SockJS协议,而是使用Python中的"普通老式WebSocket",并使用websockets包,在其中发送Stomp消息,使用stomper包。stomper包只生成字符串作为"消息",你只需使用ws.send(message)将这些消息通过WebSocket发送。

服务器上的Spring WebSockets配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/my-ws-app"); // Note we aren't doing .withSockJS() here
    }

}

在 Python 客户端代码中:

import stomper
from websocket import create_connection
ws = create_connection("ws://theservername/my-ws-app")
v = str(random.randint(0, 1000))
sub = stomper.subscribe("/something-to-subscribe-to", v, ack='auto')
ws.send(sub)
while not True:
    d = ws.recv()
    m = MSG(d)

现在d将成为一个Stomp格式的消息,它具有相当简单的格式。MSG是我编写用于解析它的快速而简单的类。
class MSG(object):
    def __init__(self, msg):
        self.msg = msg
        sp = self.msg.split("\n")
        self.destination = sp[1].split(":")[1]
        self.content = sp[2].split(":")[1]
        self.subs = sp[3].split(":")[1]
        self.id = sp[4].split(":")[1]
        self.len = sp[5].split(":")[1]
        # sp[6] is just a \n
        self.message = ''.join(sp[7:])[0:-1]  # take the last part of the message minus the last character which is \00

这并不是最完整的解决方案。没有退订功能,而且Stomp订阅的id是随机生成的,无法“记忆”。但是,stomper库提供了创建取消订阅消息的功能。

任何发送到/something-to-subscribe-to的服务器端内容都将被所有已订阅它的Python客户端接收。

@Controller
public class SomeController {

    @Autowired
    private SimpMessagingTemplate template;

    @Scheduled(fixedDelayString = "1000")
    public void blastToClientsHostReport(){
            template.convertAndSend("/something-to-subscribe-to", "hello world");
        }
    }

}

你如何将消息发送到特定的终端点?我尝试了这个:ws = create_connection("ws://host:port/prefix", header=["Authorization:Token"]) pub = stomper.send('/app/connected', 'hey server, i am client') ws.send(pub) 然而,我的服务器收到了错误消息“消息中没有用户头”。 - ngunha02

1
我已经在这里回答了一个关于从Springboot服务器通过sockJs回退向Python客户端发送STOMP消息的特定问题,使用Websockets: Websocket Client not receiving any messages。它还解决了上述评论中的以下问题:
  1. 向特定用户发送。
  2. 为什么客户端没有接收到任何消息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接