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

时间:2015-04-11 14:50:34

标签: javascript node.js websocket

我在服务器端使用带有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.");
    }
}

1 个答案:

答案 0 :(得分:7)

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

从以下论坛发帖,解决方案是

  

您需要定期让客户端ping服务器以使套接字保持活动状态。

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