Flask-socketio:sent/emit 消息的有效负载未在开发工具中正确显示

Flask-socketio: Payload of sent/emit messages not shown in devtools correctly

我刚开始将 websockets 与 Flask 结合使用。为此,我决定使用 flask-socketio 模块。代码如下所示:

#!/usr/bin/env python3

from flask import Flask, send_from_directory
from flask_socketio import SocketIO, emit, send


app = Flask(__name__, static_url_path='')
socketio = SocketIO(app)


@app.route('/')
def hello_world():
    return send_from_directory('html' ,'ws.html')


@socketio.on('connect')
def client_connected():
    # log new messages
    print('client connected')
    send('You are connected. Nice to have you here')


@socketio.on('message')
def handle_message(message):
    # echo received messages
    print(message)
    send(message)


if __name__ == '__main__':
    socketio.run(app)

对于客户端,我从 flask-socketio docs 复制了一个相当丑陋的 ws.html(位于名为 html 的文件夹中)并将其更新为最新版本的 socket.io:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.slim.js"></script>
<script type="text/javascript" charset="utf-8">
    var socket = io.connect('http://' + document.domain + ':' + location.port);
    socket.on('connect', function() {
        socket.emit('message', {data: 'I\'m connected!'});
    });
</script>

所以整体的目录结构是:

.
├── srv.py
└── html
    └── ws.html

然后我通过 Chrome 的开发者工具查看了 WebSocket 流量。但是,输出似乎不正确。连接时的欢迎消息和从 ws.html 内发送的消息都没有显示在框架的有效负载中:

为了缩小范围,我安装了 npm 模块 socketio-debugger。我不太确定它的核心functionality/usage,但至少flask的欢迎信息似乎发送正确:

$ socketio-debugger http://localhost:5000
● start Event › connect
  Connected to http://localhost:5000
❯ log Event › message
  You are connected. Nice to have you here

这是怎么回事?为什么我在 Chrome 的开发工具中得到不正确的负载?

您还需要在客户端处理已发送的消息。

当您从客户端收到 message 时,您可以再次发出一些随机消息并在客户端处理它。

瓶侧:

@socketio.on('message')
def handle_message(message):
    # echo received messages
    print(message)
    emit('custom_msg', {'msg': 'hi'})

客户端(你的ws.html

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.slim.js"></script>
<script type="text/javascript" charset="utf-8">
    var socket = io.connect('http://' + document.domain + ':' + location.port);
    socket.on('connect', function() {
        socket.emit('message', {data: 'I\'m connected!'});
    });
    socket.on('custom_msg', function(data){
        console.log(data['msg'])
    }
</script>

根据您对问题的表述方式,我猜测您构建的测试应用程序可以正常工作,而您只是在问为什么在 Chrome 开发工具。

原因是在启动 Socket.IO 连接的默认方式中,客户端首先通过长轮询连接,一旦建立连接,它们就会尝试升级到 WebSocket。因此,交换的前几件事总是经过长轮询。如果您在您的开发工具中查看 HTTP 请求,您将看到您的客户端在 POST 请求中发送的此事件。

如果你想严格在WebSocket上建立连接,你可以从客户端这样做:

var socket = io.connect(
    'http://' + document.domain + ':' + location.port,
    {transports: ['websocket']}
);

希望对您有所帮助!