【发布时间】:2016-05-31 22:37:52
【问题描述】:
我有一个 nodejs websocket 服务器,但我遇到了以下问题。
当我的客户端连接到服务器并正常终止时,在这些套接字上调用 onclose 方法,我对关闭的套接字执行清理操作。
客户端因网络断开连接时,不会调用onclose方法。是否需要设置任何超时,以便在超时后自动调用onclose?
我在 nodejs 中为 websocket 服务器使用ws 包
【问题讨论】:
我有一个 nodejs websocket 服务器,但我遇到了以下问题。
当我的客户端连接到服务器并正常终止时,在这些套接字上调用 onclose 方法,我对关闭的套接字执行清理操作。
客户端因网络断开连接时,不会调用onclose方法。是否需要设置任何超时,以便在超时后自动调用onclose?
我在 nodejs 中为 websocket 服务器使用ws 包
【问题讨论】:
默认的 ws 实现没有从客户端断开网络的回调
你可以找到一个keepAlive实现here
【讨论】:
我会尝试用两个例子来回答你的问题。尝试分析它们并了解它们的工作原理。它们都经过测试并且可以正常工作。
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>
【讨论】:
要检测断开连接,您需要有一些流量。如果您的应用程序产生持续的流量,那么您可以在每次接收到某些内容时执行诸如重置计数器之类的操作,并在计数器用完时考虑连接失败。
否则,您应该能够使用 WebSocket 提供的 ping。这些不会在浏览器中公开,但您的 Node.js 的 WebSocket 库可能允许您打开它们并在 ping 失败时收到通知。
【讨论】:
ping 和 pong 是 WebSocket 协议的一部分,应该可以工作,但是,您需要实现某种计数器以检测断开的连接。
可以在官方库documentation查看。我不想在这里复制粘贴它,因为它很快就会过时。
【讨论】: