【问题标题】:ws4py.websocket: Closing connection from client long delayws4py.websocket:从客户端长时间延迟关闭连接
【发布时间】:2018-02-24 14:21:30
【问题描述】:

我使用 ws4py.websocket 包创建了一个安全的 WebSocket 服务器。

一个 javascript 客户端连接到这个 Websocket 并向它发送一些 JSON 消息。

现在当我的 JS 客户端关闭连接 (function disconnect) 时,大约需要 30 秒才能调用服务器的 closed 函数

代码如下:

服务器

class ControlWebSocket(WebSocket):

    def opened(self):
        print("Client connected")

    def closed(self, code, reason=None):
        print("Connection closed [%d]" % (code))

    def received_message(self, m):
        #some business logic using 'm'
server = make_server('', 8999, server_class=WSGIServer, handler_class=WebSocketWSGIRequestHandler, app=WebSocketWSGIApplication(handler_cls=ControlWebSocket))
server.socket = ssl.wrap_socket (server.socket, certfile='./cert.pem', keyfile='key.pem', server_side=True)
server.initialize_websockets_manager()
server.serve_forever()

客户

ws = new WebSocket("wss://192.168.42.1:8999/");

ws.onopen = function() {
    console.log("Connected to WebSocket server");
};

ws.onmessage = function(e) {
    //some business logic using e
};

ws.onclose = function() {
    console.log("Disconnected from WebSocketServer");
};

function disconnect() {
    console.log("Disconnecting from WebSocketServer");
    ws.close();
}

关于为什么关闭连接这么长时间的任何线索?有什么方法可以更快地终止连接?

【问题讨论】:

    标签: python python-3.x websocket ws4py


    【解决方案1】:

    这是您的客户端问题。如果您查看ws 模块。在顶部你有

    const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly.
    

    然后你有下面的代码

      if (!this._finalized) {
        if (this._closeFrameReceived) this._socket.end();
    
        //
        // Ensure that the connection is cleaned up even when the closing
        // handshake fails.
        //
        this._closeTimer = setTimeout(this._finalize, closeTimeout, true);
      }
    

    这是为了确保连接不会在 30 秒之前关闭,并给每一方足够的时间来清理连接。这次是const,而不是configurable。但是,如果您希望立即终止,您可以在ws.close() 之后添加ws.finalize(),它会立即断开连接

    const WebSocket = require('ws');
    let ws = new WebSocket("wss://127.0.0.1:8999/", {
        rejectUnauthorized: false
    });
    
    ws.onopen = function() {
        console.log("Connected to WebSocket server");
    };
    
    ws.onmessage = function(e) {
        //some business logic using e
    };
    
    ws.onclose = function() {
        console.log("Disconnected from WebSocketServer");
    };
    
    function disconnect() {
        console.log("Disconnecting from WebSocketServer");
        ws.close();
        ws.finalize();
    }
    
    setTimeout(disconnect, 100)
    

    Edit-1

    深入挖掘后,ws4py 似乎有一些不符合rfc6455 的东西。

    当你从 NodeJS 进行关闭时,它会发送一个 \x88\x80 的关闭帧,表示应该关闭连接并发送一个关闭帧。文件ws4py/streaming.py 有一些问题,它无法正确响应此帧。它基本上期望读取更多数据并等待相同的数据。这会导致连接从客户端关闭,默认为 30 秒超时。

    所以这是您正在使用的 python 库中的一个错误。我使用 NodeJS WebSocket.server 创建了一个客户端,它正确关闭。

    为什么不在 NodeJS 本身中使用服务器?下面的链接有一个很好的例子来做同样的事情

    https://github.com/websockets/ws/blob/master/examples/ssl.js

    代码供参考

    'use strict';
    
    const https = require('https');
    const fs = require('fs');
    
    const WebSocket = require('..');
    
    const server = https.createServer({
      cert: fs.readFileSync('../test/fixtures/certificate.pem'),
      key: fs.readFileSync('../test/fixtures/key.pem')
    });
    
    const wss = new WebSocket.Server({ server });
    
    wss.on('connection', function connection (ws) {
      ws.on('message', function message (msg) {
        console.log(msg);
      });
    });
    
    server.listen(function listening () {
      //
      // If the `rejectUnauthorized` option is not `false`, the server certificate
      // is verified against a list of well-known CAs. An 'error' event is emitted
      // if verification fails.
      //
      // The certificate used in this example is self-signed so `rejectUnauthorized`
      // is set to `false`.
      //
      const ws = new WebSocket(`wss://localhost:${server.address().port}`, {
        rejectUnauthorized: false
      });
    
      ws.on('open', function open () {
        ws.send('All glory to WebSockets!');
      });
    });
    

    【讨论】:

    • 这更让我觉得这是服务器端的问题:客户端发送“关闭”帧,服务器也应该响应关闭帧,立即终止连接。我使用了另一个运行良好的 websocket python lib,自从我切换到 ws4py(用于 ssl 支持)后我遇到了这个问题
    • 我不能使用 Node,因为这个 websocket 控制着一个四轴飞行器,而且我所有的代码库都使用 python(我不想在它上面放置一个 Node 服务器)。很遗憾 ws4py 没有发送正确的关闭帧。我要么处理这个客户端,要么尝试另一个 python WS lib。非常感谢您的解释
    猜你喜欢
    • 2022-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 2013-08-10
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多