python - gevent-socketio 不使用我的 @app.route 端点用于 socketio

标签 python web websocket socket.io flask

我将 Flask 与 gevent-socketio 一起使用:

$ cat requirements.txt 
Flask==0.10.1
Jinja2==2.7.1
MarkupSafe==0.18
Werkzeug==0.9.3
argparse==1.2.1
gevent==0.13.8
gevent-socketio==0.3.5-rc2
gevent-websocket==0.3.6
greenlet==0.4.1
itsdangerous==0.23
wsgiref==0.1.2

我正在使用非常标准的设置来启动服务器:

#Called from __main__
def run_dev_server():
    app.debug = True
    port = 5000
    dapp = werkzeug.debug.DebuggedApplication(app, evalex = True)
    SocketIOServer(('', port), dapp, resource="socket.io").serve_forever()

还有一个非常标准的钩子(Hook),用于我的 SocketIO 命名空间:

@app.route('/socket.io/<path:rest>')
def push_stream(rest):
    print 'ws connect', rest
    try:
        socketio.socketio_manage(request.environ, {'/join_notification': JoinsNamespace}, request)
    except Exception as e:
        app.logger.error("Exception while handling socketio connection", exc_info=True)
    return flask.Response()

但是,我遇到了客户端未触发“连接”事件的问题。经过一番挖掘,我意识到即使我得到了 127.0.0.1 - - [2013-08-19 12:53:57] "GET/socket.io/1/websocket/170191232666 HTTP/1.1"101 - - 输出中的消息,我没有收到 ws connect 消息(而代码中的其他打印语句工作正常)。我注释掉了那个端点,果然它甚至没有被调用。这可以解释为什么我的命名空间没有被使用。但为什么?我是否注册了我的命名空间错误?

打印 app.url_map 产生:

Map([<Rule '/' (HEAD, OPTIONS, GET) -> root>,
 <Rule '/socket.io/<rest>' (HEAD, OPTIONS, GET) -> push_stream>,
 <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])

所以没有什么不寻常的。

编辑:客户端代码:

socket = io.connect('/join_notification')
console.log(socket)

socket.on('connect', function() {
    console.log('connected to websocket')
    socket.emit('login', {'name': data['name']})
})

socket.on('disconnect', function() {
    console.log('d/c\'d from websocket')
})

socket.on('join_error', function() {
    ...
})

socket.on('join_success', function(data){
    ...
})

socket.on('join', function(data) {
    ...
})

最佳答案

奇怪的行为是因为这一行:

dapp = werkzeug.debug.DebuggedApplication(app, evalex = True)

Socketio 和 werkzeug 调试器不能一起工作。已经有关于此的未解决问题,请参阅:https://github.com/abourget/gevent-socketio/issues/114

但是您可以通过制作自定义调试器类来解决这个问题。

from werkzeug.debug import DebuggedApplication
class MyDebuggedApplication(DebuggedApplication):
    def __call__(self, environ, start_response):
        # check if websocket call
        if "wsgi.websocket" in environ and not environ["wsgi.websocket"] is None:
            # a websocket call, no debugger ;)
            return self.app(environ, start_response)
        # else go on with debugger
        return DebuggedApplication.__call__(self, environ, start_response)

# remember to call the overwritten debugger in your run_dev_server() function
dapp = MyDebuggedApplication(app, evalex = True)

补丁依赖于环境 key wsgi.websocket,它似乎只存在于 websocket 调用中。小心,我没有考虑太多,可能还有其他问题。

关于python - gevent-socketio 不使用我的 @app.route 端点用于 socketio,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18319345/

相关文章:

javascript - 如何使用来自网络套接字的网络音频 API 流式传输音频 block ?

python - 如何从 python 程序生成多个 python 脚本?

python - 使用 Sqlalchemy 时 Session_scope 引发属性错误

python - Python 的按位求补运算符 (~ 代字号) 是如何工作的?

javascript - 在中文网络上测试网站

javascript - 通过带有客户端证书身份验证的安全 http 服务器的 Websocket

python - 无法使用 Scapy sendp() 发送 MPTCP 数据包

java - 如何将字段绑定(bind)到bean vaadin中的外键

javascript - 我正在寻找一种在 Vuetify 中保持底部导航图标颜色的方法

c++ - Boost::Beast Websocket 双向流 (C++)