websockets / ws

Simple to use, blazing fast and thoroughly tested WebSocket client and server for Node.js
MIT License
21.64k stars 2.42k forks source link

Send data in "Dectect Broken Connections", but then onmessage not working #1438

Closed tedpenk closed 6 years ago

tedpenk commented 6 years ago

Hello,I have some problem in use the recommanded "Dectect broken connections" method,my code :

const WebSocket = require("ws");

const wss = new WebSocket.Server({noServer: true});

const conn = {
    master: {},
    slave: {}
}

const otherNameMap = {
    'master': 'slave',
    'slave': 'master'
};

function send(ws,msg){
    try {
        ws.send(msg);
    }catch (e) {
        logger.error(e);
    }
}

function noop() {}

function heartbeat() {
  this.isAlive = true;
}

wss.on('connection', ws => {
    const url = ws.upgradeReq.url;

    const res = /\/peer\/([\w]+)\/([\w]+)/.exec(url);
    const role = res[1], id = res[2];

    if (['master', 'slave'].indexOf(role) === -1) {
        const error = `url error ${url}`;
        logger.error(error);
        ws.close(1011, error);
        return;
    }

    function getOtherWs() {
        return conn[otherNameMap[role]][id];
    }

    conn[role][id] = ws;
    ws.isAlive = true;
    ws.on('pong', heartbeat);

    ws.on('message', data => {
        let otherWs = getOtherWs();
        if (data === 'heart beat' && ws.readyState === WebSocket.OPEN) {
            send(ws, 'heart beat');
            if (otherWs && otherWs.readyState === WebSocket.OPEN) {
                send(otherWs, 'request delay');
            }
            return;
        }

        if (data === 'response delay' && otherWs && otherWs.readyState === WebSocket.OPEN) {
            send(otherWs, 'response delay');
            return;
        }

        if (otherWs && otherWs.readyState === WebSocket.OPEN) {
            send(otherWs,data);
        }
    });
});

function getOtherByWS(ws) {
    const res = /\/peer\/([\w]+)\/([\w]+)/.exec(ws.upgradeReq.url);
    const role = res[1], id = res[2];
    return conn[otherNameMap[role]][id]
}

const interval = setInterval(ping => {
    wss.clients.forEach((ws, index) => {
        let otherWs = getOtherByWS(ws);
        if (!ws.isAlive) {
            if (otherWs && otherWs.readyState === WebSocket.OPEN) {
                send(otherWs, 'other offline');
            }
        }
        else {
            if (otherWs && otherWs.readyState === WebSocket.OPEN) {
                send(otherWs, 'other online');
            }
        }
        if (ws.readyState === WebSocket.OPEN) {
            ws.isAlive = false;
            ws.ping(noop);
        }
    });
}, 10000);

module.exports = wss;

The otherWs is another websocket client that connected to this server,I want to send 'offline', 'online' signal to it when another client connection's status changed.

The code is running well,But the problem is when I set setInterval second agrument to less than 10000ms (for example 9000ms, 8000ms, 5000ms and so on),the ws's onmessage method can not receive data anymore. I use ws._socket.on('data', data => {}), It's work, but ws.on('message', data => {}) is not working! I need the dectect code run at least every 5000ms, so I want to know what happened and how to fix it, Thank you very much!

version:v6.0.0 Node.js version(s): v9.9.0 OS version(s): os x10.12.6

lpinca commented 6 years ago

Sorry but I don't understand the issue. Can you please simplify your test case? Make it as small as possible and reproducible.

tedpenk commented 6 years ago

It's my mistake,so I close this issue.