蟒蛇Socket.IO客户端发送广播消息TornadIO2服务器(python Socket.IO

2019-06-25 09:18发布

我建立一个实时的Web应用程序。 我希望能够从服务器端实现我的Python应用程序发送广播消息。

下面是设置:

  • socketio.js在客户端
  • TornadIO2服务器Socket.IO服务器
  • 在服务器侧Django的框架)

我可以成功地从客户端发送socket.io消息发送到服务器。 服务器处理这些,并且可以发送响应。 在下文中,我将介绍我是如何做到这一点。

当前设置和代码

首先,我们需要确定哪些处理socket.io事件连接:

class BaseConnection(tornadio2.SocketConnection):
    def on_message(self, message):
        pass

    # will be run if client uses socket.emit('connect', username)
    @event
    def connect(self, username):
        # send answer to client which will be handled by socket.on('log', function)
        self.emit('log', 'hello ' + username)

启动服务器由一个Django管理自定义的方法来完成:

class Command(BaseCommand):
    args = ''
    help = 'Starts the TornadIO2 server for handling socket.io connections'

    def handle(self, *args, **kwargs):
        autoreload.main(self.run, args, kwargs)

    def run(self, *args, **kwargs):
        port = settings.SOCKETIO_PORT

        router = tornadio2.TornadioRouter(BaseConnection)

        application = tornado.web.Application(
            router.urls,
            socket_io_port = port
        )

        print 'Starting socket.io server on port %s' % port
        server = SocketServer(application)

很好,现在服务器上运行。 让我们添加的客户端代码:

<script type="text/javascript">    
    var sio = io.connect('localhost:9000');

    sio.on('connect', function(data) {
        console.log('connected');
        sio.emit('connect', '{{ user.username }}');
    });

    sio.on('log', function(data) {
        console.log("log: " + data);
    });
</script>

显然{{ user.username }}将由的当前登录的用户,在这个例子中,用户名是“高山”用户名替换。

现在,每次页面被刷新时,控制台输出为:

connected
log: hello alp

因此,调用消息和发送响应工作。 但现在到了棘手的部分。

问题

响应“你好ALP”仅被发送到socket.io消息的调用。 我想,如果一个新用户加入队伍(例如,在一个聊天应用)广播消息给所有连接的客户端,以便他们可以实时通知。

所以,这里是我的问题:

  1. 我怎么能发送广播消息到所有连接的客户端?

  2. 我怎么能发送广播消息给多个连接的客户端所上的特定频道订阅?

  3. 如何我在Python代码的任何地方发送广播消息(外面的BaseConnection类)? 这会需要某种Socket.IO客户端的蟒蛇,或者这是内置有TornadIO2?

所有这些节目应以可靠的方式来完成,所以我猜的WebSockets是最好的选择。 但我向所有人开放的良好解决方案。

Answer 1:

我最近写了一个类似的设置非常类似的应用程序,所以我有几点启示。

做你需要的正确的方法是有一个发布 - 订阅后端。 这里只有这么多,你可以用简单的做ConnectionHandler秒。 最后,处理连接的类级组开始变得丑陋(更不用提车)。

理想情况下,你会想使用类似的Redis,与异步绑定龙卷风(看看brukva )。 这样,你不必惹注册客户特定的渠道 - Redis的具有全部开箱。

从本质上讲,你有这样的事情:

class ConnectionHandler(SockJSConnection):
    def __init__(self, *args, **kwargs):
        super(ConnectionHandler, self).__init__(*args, **kwargs)
        self.client = brukva.Client()
        self.client.connect()
        self.client.subscribe('some_channel')

    def on_open(self, info):
        self.client.listen(self.on_chan_message)

    def on_message(self, msg):
        # this is a message broadcast from the client
        # handle it as necessary (this implementation ignores them)
        pass

    def on_chan_message(self, msg):
        # this is a message received from redis
        # send it to the client
        self.send(msg.body)

    def on_close(self):
        self.client.unsubscribe('text_stream')
        self.client.disconnect()

请注意,我用sockjs,龙卷风 ,我发现比socket.io稳定得多。

无论如何,一旦你有这种设置的,从任何其他客户端发送消息(如Django的,你的情况)是打开一个Redis的连接容易( Redis的-PY是一个安全的赌注),并发布一条消息:

import redis
r = redis.Redis()
r.publish('text_channel', 'oh hai!')

这个答案竟然很长,所以我去加倍努力,并提出了博客文章出来的: http://blog.y3xz.com/blog/2012/06/08/a-modern-python-stack-for-一个实时的Web应用程序/



Answer 2:

我写在这里,因为它是在评论部分很难写。 您可以查看示例目录tornadoio2例子,你可以找到实现聊天,同时:

class ChatConnection(tornadio2.conn.SocketConnection):
    # Class level variable
    participants = set()

    def on_open(self, info):
        self.send("Welcome from the server.")
        self.participants.add(self)

    def on_message(self, message):
        # Pong message back
        for p in self.participants:
            p.send(message)

正如你可以看到他们实现参与者设置))



Answer 3:

如果您已经使用Django,为什么不看看GEVENT-socketio。



文章来源: python Socket.IO client for sending broadcast messages to TornadIO2 server