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

标签 javascript node.js websocket

我在服务器端使用 ws 和 node.js,在客户端使用常规的 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.");
    }
}

最佳答案

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

从下面的论坛帖子,解决方案是

you'll need to make your clients ping the server periodically to keep the socket alive.

这不是最理想的情况,但确实可行。感谢您为我指明正确的方向。

关于javascript - 为什么我的 websocket 会在几分钟后关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29579208/

相关文章:

javascript - document.querySelectorAll 选择特定输入的 id

node.js - 如何在 Node.js 中处理回调?

node.js - 如何在nodeJs上查询mongoose中的两个集合?

javascript - 将 WebSockets 移入工作线程的原因

python - 如何在 Windows 上将 websockify 与 python 一起使用或将 websockify 编译为 Windows 可执行文件(一次用于多个客户端连接)

javascript - 尝试从可观察数组中获取特定元素

javascript - 从javascript动态生成的DIV位置问题

javascript - 当用户在文本字段中输入信息并单击js中的提交时,如何显示确认提示,显示已输入的内容

node.js - DynamoDB - 使用 NodeJS 扫描和过滤 map

websocket - netty websocket 协议(protocol)支持