nodejs websocket检测断开连接的套接字

Posted

技术标签:

【中文标题】nodejs websocket检测断开连接的套接字【英文标题】:nodejs websocket detect disconnected socket 【发布时间】:2016-05-31 22:37:52 【问题描述】:

我有一个 nodejs websocket 服务器,但我遇到了以下问题。

当我的客户端连接到服务器并正常终止时,在这些套接字上调用 onclose 方法,我对关闭的套接字执行清理操作。

客户端因网络断开连接时,不会调用onclose方法。是否需要设置任何超时,以便在超时后自动调用onclose

我在 nodejs 中为 websocket 服务器使用ws 包

【问题讨论】:

【参考方案1】:

默认的 ws 实现没有从客户端断开网络的回调

你可以找到一个keepAlive实现here

【讨论】:

【参考方案2】:

我会尝试用两个例子来回答你的问题。尝试分析它们并了解它们的工作原理。它们都经过测试并且可以正常工作。

1- 网络套接字:

服务器:

var WebSocketServer = require('websocket').server;
var http = require('http');

var server = http.createServer(function(request, response) 
    console.log((new Date()) + ' Received request for ' + request.url);
    response.writeHead(404);
    response.end();
);
server.listen(3000, function() 
    console.log((new Date()) + ' Server is listening on port 3000');
);

wsServer = new WebSocketServer(
    httpServer: server,
    autoAcceptConnections: false
);

function originIsAllowed(origin) 
  return true;


wsServer.on('request', function(request) 
    if (!originIsAllowed(request.origin)) 
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    

    var connection = request.accept('echo-protocol', request.origin);
    console.log((new Date()) + ' Connection accepted.');
    connection.on('message', function(message) 
        if (message.type === 'utf8') 
            console.log('Received Message: ' + message.utf8Data);
            connection.sendUTF(message.utf8Data);
        
        else if (message.type === 'binary') 
            console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
            connection.sendBytes(message.binaryData);
        
    );
    connection.on('close', function(reasonCode, description) 
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    );
);

客户:

<!DOCTYPE html>
<html>
<head>
    <title>Web socket Experiment</title>
    <script type="text/javascript">
        function callWebSocket() 

            var socket = new WebSocket("ws://localhost:3000", 'echo-protocol');

            socket.onopen = function () 
                alert("Hello, Connected To WS server");
            ;

            socket.onmessage = function (e) 
                alert("The message received is : " + e.data);
            ;
            socket.onerror = function (e) 
                alert("An error occured while connecting... " + e.data);
            ;
            socket.onclose = function () 
                alert("hello.. The coonection has been clsoed");
            ;

        
    </script>
</head>

<body>
    <input type="button" value="Open Connecton" onclick="callWebSocket()" />
</body>
</html>

2- Socket.io:

服务器:

var http = require('http');
    var app = require('express')();
    var httpServer = http.createServer(app)
    var io = require('socket.io')(httpServer);

app.get('/', function(req, res) 
    res.sendfile(__dirname + '/index.html');
);

io.on('connection', function(socket) 
    socket.emit('news', 
        hello: 'world'
    );
    socket.on('my other event', function(data) 
        console.log(data);
    );
    socket.on('disconnect', function(data) 
        console.log('disconnect!');
    );
);

httpServer.listen(3000);

客户:

<html>
<head>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
  var conn_options = 
    'sync disconnect on unload':false
  ;
  var socket = io.connect('http://localhost:3000',conn_options);
  socket.on('news', function (data) 
    console.log(data);
    socket.emit('my other event',  my: 'data' );
  );
</script>
</head>
<body>
</body>
</html>

【讨论】:

我忘了提到我正在使用来自 npm 的 ws 包作为 websocket 服务器。 npmjs.com/package/ws。似乎它没有通知断开连接。【参考方案3】:

要检测断开连接,您需要有一些流量。如果您的应用程序产生持续的流量,那么您可以在每次接收到某些内容时执行诸如重置计数器之类的操作,并在计数器用完时考虑连接失败。

否则,您应该能够使用 WebSocket 提供的 ping。这些不会在浏览器中公开,但您的 Node.js 的 WebSocket 库可能允许您打开它们并在 ping 失败时收到通知。

【讨论】:

pingpong 是 WebSocket 协议的一部分,应该可以工作,但是,您需要实现某种计数器以检测断开的连接。【参考方案4】:

可以在官方库documentation查看。我不想在这里复制粘贴它,因为它很快就会过时。

【讨论】:

以上是关于nodejs websocket检测断开连接的套接字的主要内容,如果未能解决你的问题,请参考以下文章

套接字 IO - 新会话触发断开连接

Web Socket:无法在 Internet 断开连接时检测到客户端连接

通过 websockets 的 Socket.io - 随机“传输端”断开连接

WebSocket 在几个时间间隔之间不断断开连接

如何在WebSocket的服务器侧检测客户端的断开连接

如何检测 TCP 套接字断开连接(使用 C Berkeley 套接字)