• Twisted 与 Tornado 中的 WebSocket 连接问题及解决方案


    在这里插入图片描述

    1、问题背景

    项目中我们需要通过 Tornado HTTP 处理程序建立WebSocket连接,该连接需要处理多个用户请求,并且将从外部服务器获取的数据存储到数据库中。我们尝试了以下实现:

    from twisted.internet import reactor
    from autobahn.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS
    from tornado.options import define, options, parse_command_line
    
    class IndexHandler(tornado.web.RequestHandler):
        @tornado.web.asynchronous
        def get(self):
            self.write("This is your response")
            factory = WebSocketClientFactory("ws://localhost:7096")
            factory.protocol = BridgeSocket
            connectWS(factory)
            self.finish()
            reactor.run()
    
    class BridgeSocket(WebSocketClientProtocol):
    
        def sendHello(self):
            self.sendMessage("rails")
    
        def onOpen(self):
            self.sendHello()
    
        def onMessage(self, msg, binary):
            print "Got echo: " + msg
    
        def onClose(wasClean,code,reason):
            print "GETTING CLOSE CONNECTION"
            print str(wasClean)+" ---"+str(code)+"---"+str(reason)
            reactor.stop()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    但是,reactor.run()会阻止对Tornado Web服务器的进一步HTTP请求,如果我们在WebSocket工作完成后立即调用reactor.stop(),又会发现无法重新启动reactor。

    2、解决方案

    为了在Tornado中运行AutobahnPython的WebSocket客户端,我们需要使用Twisted-Tornado集成(“Twisted on Tornado”)。这个库允许我们在Tornado中运行Twisted reactor循环。

    以下是如何使用Twisted on Tornado来解决问题的步骤:

    1. 安装Twisted on Tornado:
    pip install twisted-tornado
    
    • 1
    1. 在你的Tornado应用程序中导入Twisted on Tornado:
    from twisted.internet import reactor
    from twisted.internet.defer import Deferred
    from tornado.ioloop import IOLoop
    
    • 1
    • 2
    • 3
    1. 在你的Tornado HTTP处理程序中,使用Twisted on Tornado的reactor来运行WebSocket客户端:
    def main():
        reactor.suggestThreadPoolSize(1)  # Increase threadpool size for multiple persistent connections
        IOLoop.instance().run(True)
    
    reactor.callWhenRunning(main)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 修改你的WebSocket客户端协议类,使其继承自Twisted的WebSocketClientFactory:
    class BridgeSocket(WebSocketClientFactory):
        def buildProtocol(self, addr):
            return BridgeSocketProtocol()
    
    class BridgeSocketProtocol(WebSocketClientProtocol):
    
        def sendHello(self):
            self.sendMessage("rails")
    
        def onOpen(self):
            self.sendHello()
    
        def onMessage(self, msg, binary):
            print "Got echo: " + msg
    
        def onClose(self, wasClean, code, reason):
            print "GETTING CLOSE CONNECTION"
            print str(wasClean)+" ---"+str(code)+"---"+str(reason)
            reactor.stop()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 在你的Tornado应用程序中,使用Twisted on Tornado的reactor来连接到WebSocket服务器:
    from twisted.internet import reactor
    
    def connect_to_websocket():
        factory = BridgeSocket()
        reactor.connectTCP("localhost", 7096, factory)
    
    reactor.callWhenRunning(connect_to_websocket)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这样,我们就可以在Tornado中使用AutobahnPython的WebSocket客户端,而不会阻止对Tornado Web服务器的进一步HTTP请求。

  • 相关阅读:
    从五大维度数据解析以太坊合并前后的变化
    Ubuntu 上使用nginx部署vue项目
    Python 通过datetime 获取上周,上月,上年的时间段 附代码
    cnpm安装步骤
    【数学建模】实验设计方法
    SpringMVC教程
    HTML5特殊属性
    [附源码]Python计算机毕业设计SSM街舞公司管理系统(程序+LW)
    c语言小项目(排雷游戏实现)
    我的创作纪念日
  • 原文地址:https://blog.csdn.net/huakej_/article/details/138112938