简体   繁体   English

ws4py.websocket:从客户端长时间延迟关闭连接

[英]ws4py.websocket: Closing connection from client long delay

I created a secure WebSocket server using the ws4py.websocket package. 我使用ws4py.websocket包创建了一个安全的WebSocket服务器。

A javascript client connects to this Websocket and sends some JSON messages to it. javascript客户端连接到此Websocket并向其发送一些JSON消息。

Now when my JS client closes the connection ( function disconnect ), it takes about 30 secondes before the server's closed function gets called 现在当我的JS客户端关闭连接( function disconnect )时,在调用服务器的closed函数之前需要大约30个secondes

Here's the code: 这是代码:

Server 服务器

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()

Client 客户

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();
}

Any clues on why this is so long to close the connection ? 关于为什么这么长时间关闭连接的任何线索? Are there any ways to terminate the connection faster ? 有没有办法更快地终止连接?

This your client side issue. 这是您的客户端问题。 If you look in the ws module. 如果你查看ws模块。 At the top you have 在你的顶部

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

And then you have below code 然后你有下面的代码

  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);
  }

Which is to ensure the connection doesn't close before 30 second and gives each party enough time to cleanup the connection. 这是为了确保连接在30秒之前不会关闭,并为每一方提供足够的时间来清理连接。 This time is a const and not configurable as such. 这个时间是一个const ,不能这样configurable But if you want the termination to happen instantly you can add a ws.finalize() after ws.close() and it would disconnect immediately 但是,如果你想立即发生终止,你可以在ws.finalize()之后添加一个ws.close() ,它会立即断开连接

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 编辑-1

After digging deeper it seems the ws4py has some stuff not in accordance to rfc6455 . 在深入挖掘后,似乎ws4py有一些不符合rfc6455的东西。

When you do a close from NodeJS, it sends a close frame of \\x88\\x80 which indicates that connection should be closed and a close frame should be sent. 当您从NodeJS关闭时,它会发送一个\\x88\\x80的关闭帧,表示应该关闭连接并应该发送一个关闭帧。 The file ws4py/streaming.py has some issues where it doesn't respond to this frame properly. 文件ws4py/streaming.py存在一些问题,它无法正确响应此帧。 It basically expects more data to be read and gets stuck waiting for the same. 它基本上期望读取更多数据并等待相同的数据。 This cause the connection to be closed from the client side with the default 30 second timeout. 这会导致从客户端关闭连接,默认为30秒超时。

So this is a bug in the python library which you are using. 所以这是你正在使用的python库中的一个错误。 I created a client using NodeJS WebSocket.server it closed properly. 我使用NodeJS WebSocket.server创建了一个客户端,它正确关闭。

Why don't you use the Server in NodeJS itself? 为什么不在NodeJS中使用Server? There is a great example for doing the same at below link 在下面的链接中有一个很好的例子

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

code here for reference 代码在这里供参考

'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!');
  });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM