为什么我的websocket在几分钟后closures?

我在服务器端使用ws和node.js,在客户端使用常规的WebSocket API。 打开连接和消息几次来回工作正常。 但是套接字在一两分钟后总是closures。 难道他们不应该坚持? 难道我做错了什么?

我的服务器是托pipe在heroku上的node.js。 我只是使用foreman start (heroku工具在本地运行服务器)再次本地testing,并且套接字根本不会意外closures,所以也许这是对heroku的错误configuration。 无论如何,这里有一个相关的代码示例,为简洁起见省略了一些function。

我在OSX Yosemite的Chrome上testing了这个应用程序,但是在运行在生产环境中的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."); } } 

感谢大家的评论。 事实certificate,jfriend00有正确的答案,我只是没有意识到,我使用的托pipe服务不允许连接保持开放。

从下面的论坛发帖,解决scheme是

您需要定期使服务器ping服务器以保持套接字的活跃。

不是最理想的情况,但的确是可行的。 谢谢你指出我正确的方向。

https://discussion.heroku.com/t/websocket-closes-after-60-seconds/333