为啥我的 websocket 在几分钟后关闭?
Posted
技术标签:
【中文标题】为啥我的 websocket 在几分钟后关闭?【英文标题】:Why does my websocket close after a few minutes?为什么我的 websocket 在几分钟后关闭? 【发布时间】:2015-04-11 14:50:33 【问题描述】:我在服务器端使用带有 node.js 的 ws,在客户端使用常规的 WebSocket API。来回打开连接和消息几次工作正常。但是套接字总是在一两分钟后关闭。他们不应该坚持吗?我做错了吗?
我的服务器是托管在 heroku 上的 node.js。我刚刚使用foreman start
(在本地运行服务器的heroku工具)再次在本地进行了测试,并且套接字根本没有意外关闭,所以这可能是heroku的错误配置。无论如何,这是一个相关的代码示例,为简洁起见省略了一些函数。
我正在 OSX Yosemite 上的 Chrome 中测试该应用程序,但在 Windows 7 上的 Chrome 中针对生产环境运行时看到了相同的行为。
服务器:
// Client <-> Host Protocol functions. Move to a different file so that they can be shared.
var C2H_SIGNAL_TYPE_REGISTER = "register";
var H2C_SIGNAL_WELCOME = "welcome";
var H2C_SIGNAL_TYPE_ERROR = "error";
var H2C_SIGNAL_TYPE_PEER_ADDED = "peer_joined";
var H2C_SIGNAL_TYPE_PEER_LEFT = "peer_left";
// Update channel endpoint names.
var UPDATE_ENDPOINT_PEERS = "/peers";
// Create a signal message with all asociated default properties.
// Signal senders should create this object and update it accordingly when
// building a signal message to send to a peer.
function createHostMsg(type)
var msg = signalType: type ;
if ( type == H2C_SIGNAL_WELCOME )
// Since we're sending a welcome message, we need to provide a list
// of currently connected clients.
msg.peers = ;
for ( var addr in clients )
console.log("addr " + addr);
var c = clients[addr].description;
if ( c && c.id )
msg.peers[c.id] = c;
return msg;
// require modules.
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var multer = require('multer');
// Tracks connected peers.
var clients = ;
// 1. Configure the application context settings.
var app = express();
app.enable('trust proxy');
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json()); // parse json
app.use(bodyParser.urlencoded( extended: true )); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data
// a. configure http routers. these will handle requests coming from app.
app.set('port', (process.env.PORT || 5000));
app.get('/app', peerApp);
app.get('/script/:name', publicScriptRouter);
// 2. Create the http server itself, passing app to be the request handler.
// app will handle routing and multiplexing of incoming requests to different
// route middleware handlers.
var http = require('http');
var WebSocketServer = require("ws").Server
var httpServer = http.createServer(app);
httpServer.listen( app.get('port') );
// 3. Create one of these for all socket endpoints.
var wss = new WebSocketServer( server: httpServer, path: UPDATE_ENDPOINT_PEERS );
wss.on("connection", function(webSocket)
// 1. Associate the socket with the remote address it came from.
var remoteAddress = webSocket._socket.remoteAddress;
var remotePort = webSocket._socket.remotePort;
var clientConnID = remoteAddress + ":" + remotePort;
var exists = clients[clientConnID] != null;
if ( exists )
console.log("socket server connection: associating new connection from %s with registered peer.", clientConnID);
clients[clientConnID].socket = webSocket;
else
console.log("socket server connection: associating new connection from %s with unregistered peer.", clientConnID);
clients[clientConnID] = description: null, socket: webSocket ;
// 2. Hook up handlers for communication over this particular socket.
webSocket.on("message", function(data, flags)
processMessage(webSocket, data, flags);
);
webSocket.on("close", function()
// Praise satin for closures!!
removePeer(clientConnID);
);
);
// Transduce the message and handle it accordingly.
function processMessage(socket, data, flags)
var msg = JSON.parse(data);
if ( !msg.signalType )
var msg = createHostMsg( H2C_SIGNAL_TYPE_ERROR );
msg.errStr = "message_malformed";
socket.send( JSON.stringify( msg ) );
else if ( msg.signalType == C2H_SIGNAL_TYPE_REGISTER )
handleRegistration(socket, msg);
客户:
function initSignalChannel()
rtcPeer.channel = new WebSocket( location.origin.replace(/^http/, 'ws') + "/peers" );
rtcPeer.channel.onmessage = updateChannelMessage;
rtcPeer.channel.onopen = function(event)
console.log("remote socket opened");
rtcPeer.channel.onclose = function(event)
console.log("host closed remote socket.");
function updateChannelMessage(event)
var msgObj = JSON.parse(event.data);
if ( !msgObj || !msgObj.signalType )
console.log("updateChannelMessage: malformed response!! %o", msgObj );
else if ( msgObj.signalType == "welcome" )
console.log("updateChannelMessage: received welcome from host.");
handleWelcome(msgObj);
else if ( msgObj.signalType == "peer_joined" )
console.log("updateChannelMessage: received peer_joined from host.");
if ( msgObj.peer.id == rtcPeer.description.id )
console.log("updateChannelMessage: peer_joined: received notification that I've been added to the room. " + msgObj.peer.id);
console.log(msgObj);
else
console.log("updateChannelMessage: peer_joined: peer %s is now online.", msgObj.peer.id);
console.log(msgObj);
addRemotePeer( msgObj.peer );
function addRemotePeer(peerObj)
remotePeers[peerObj.id] = peerObj;
var ui = createPeerUIObj(peerObj);
$("#connectedPeerList").append( ui );
function createPeerUIObj(peerObj)
var ui = null;
if ( peerObj )
ui = $("<li></li>");
var a = $("<a></a>");
a.append("peer " + peerObj.id);
ui.append(a);
ui.click(function(event) console.log("clicked"););
return ui;
function handleWelcome(msgObj)
if ( msgObj.id )
console.log("updateChannelMessage: welcome: received id from host. " + msgObj.id);
console.log(msgObj);
rtcPeer.description.id = msgObj.id;
for ( var p in msgObj.peers )
addRemotePeer(msgObj.peers[p]);
else
console.log("updateChannelMessage: malformed response. no id.");
【问题讨论】:
发布你的node.js代码和你的客户端代码,没有它我们帮不了你 还值得描述一下您的服务器基础架构(托管设施、代理等),因为有些不允许长时间运行的非活动套接字。 看起来您安装了不支持 websocket 的防火墙或防病毒过滤器代理。但正如 Marco 和 jfriend00 已经说过的那样,了解您的代码和您的环境会很有用。 谢谢大家。整理一个适当的描述,很快就会回复你。欣赏它。 这几分钟连接是否空闲?空闲的 tcp 连接通常会被一端或另一端关闭。 【参考方案1】:感谢大家的cmets。原来 jfriend00 有正确的答案,我只是没有意识到我使用的托管服务不允许保持连接。
从下面的论坛帖子中,解决方案是
您需要让您的客户端定期 ping 服务器以保持套接字处于活动状态。
不是最理想的情况,但确实可行。感谢您为我指明正确的方向。
【讨论】:
以上是关于为啥我的 websocket 在几分钟后关闭?的主要内容,如果未能解决你的问题,请参考以下文章
我的 OpsWorks 实例在关闭五分钟后自行启动 - 为啥?
为啥 websocket 在使用代码 1000 响应本机打开后立即关闭。(iOS)