如何在服务器端发出Socket IO事件

时间:2013-03-20 22:04:34

标签: python django websocket socket.io gevent-socketio

我正在运行gevent-socketio Django应用程序。

我有类似这个类的东西

@namespace('/connect')
class ConnectNamespace(BaseNamespace):

    def on_send(self, data):
        # ...

但是,如果我从javascript客户端收到事件,一切正常,例如send事件处理正确

如果我想在服务器端emit某个事件,我有点迷失。我可以使用socket.send_packet

在课堂上完成

但是现在我想将一些事件链接到post_save信号,所以我想从这个命名空间类之外的send_packet,这样做的一种方法是

ConnectNamespaceInstance.on_third_event('someeventname')

我无法弄清楚如何获取ConnectNamespaceInstance的实例

总结一下,我只想在收到post_save信号后向javascript客户端发送一个事件

2 个答案:

答案 0 :(得分:7)

你可能想要做的是添加一个模块变量来跟踪连接,比如说_connections,如下所示:

_connections = {}

@namespace('/connect')
class ConnectNamespace(BaseNamespace):

然后添加initializedisconnect方法,这些方法使用您稍后可以参考的一些快乐标识符:

def initialize(self, *args, **kwargs):
    _connections[id(self)] = self
    super(ConnectNamespace, self).initialize(*args, **kwargs)

def disconnect(self, *args, **kwargs):
    del _connections[id(self)]
    super(ConnectNamespace, self).disconnect(*args, **kwargs)

当您需要生成活动时,您可以在_connections变量中查找正确的连接,然后使用emit启动活动。

(没有测试任何这个,但我在许多其他语言中使用了类似的模式:没有看到为什么这在Python中也不起作用的原因。)

答案 1 :(得分:0)

除了Femi的答案,我认为肯定有效。使用Redis可能会给你更多的灵活性,并且使用gevent中的greenlet可能会在框架中更多地使用这种方法"因为你已经在使用gevent-socketio了:D

REDIS_HOST = getattr(settings, 'REDIS_HOST', '127.0.0.1')


class YourNamespace(BaseNamespace):

    def _listener(self, channel_label_you_later_call_in_post_save):
        pubsub = redis.StrictRedis(REDIS_HOST).pubsub()
        pubsub.subscribe(chan)
        while True:
            for i in pubsub.listen():
                self.send({'message_data': i}, json=True) 

    def recv_message(self, message):
        if is_message_to_subscribe(message):
            self.spawn(self.listener, get_your_channel_label(message))

在你的post_save中,你可以做到

red = redis.StrictRedis(REDIS_HOST)
red.publish(channel_label, message_data)