I get an error message on the server saying "Found error: Error: write EPIPE" when I use the following code to send messages from server to client and use an error listener. The error message is from the error listener I write on server. (Some codes are on the client which I didn't post here)
try {
ws.send(msg, function(error) {
if(error == undefined)
return;
else
logger.debug("Async error:"+error);
});
} catch(e) {
logger.debug("Sync error: " + e);
ws.close();
}
wss.on('error', function error(err) {
console.log('Error: ' + err.code);
});
Error listener is inside wss.on('connection', function(ws, req) {}):
ws.on('error', function(err) {
logger.debug('Found error: ' + err);
});
ws.on('close', function() {
logger.debug('connection closed.');
});
When I get this error, the client closes (readyState is not open), but the server keeps running. Is there anything I can do to figure out what causes the error and closes the client? I am running a realtime game. I didn't do anything special other than just run the client normally and the client computer is in my room. I wonder if this is related to the server thinking the client is in idle status. For example, when I send little data from client to the server, the client crashes, when I keep pressing the mouse button, it sends messages to the server very often and the client is always alive.
I have used the "ping-pong" code on the server. But not sure if I need to implement that on the client.
Hi, you already posted the same question here https://github.com/websockets/ws/issues/1170#issuecomment-314807518.
EPIPE means you're writing to a socket when the other end has terminated the connection.
It's a runtime error and there is nothing you can do to avoid it. You only have to close your end as well but that is done automatically.
You can find more info here https://github.com/websockets/ws/issues/1017.
All you have to do is adding an error listener:
wss.on('connection', (ws) => {
ws.on('error', handleError);
});
Wrapping ws.send() in a try...catch statement doesn't make sense if you are already passing a callback to ws.send().
I have no idea why your client closes the connection.
Thanks for your reply. Sorry to create a new issue but I hope you can have a look at this.
I already have the error listener. That's why it sends the message on server instead of stopping the server. I just want to know if this is related to client being assumed idle if no data is sent to the server for half a minute.
You are sending pings so that is unlikely but I can't really know what happens on your environment. Try to use wireshark and see what happens.
I have already tried wireshark sniffing before I ask here. But I can't find anything useful as when the connection is closed the server just try to resend data again and again and ignore the ACK message.
Are you able to create a minimal (using only ws) reproducible test case? If not it's hard to help.
That is hard to reproduce using only ws. I need to figure out some other way. But when I am testing it today. I found that after a while all sockets are terminated. I use the following code:
function heartbeat() {
this.isAlive = true;
}
wss.on('connection', function(ws, req) {
const interval = setInterval(function ping() {
wss.clients.forEach(function each(ws) {
if (ws.isAlive === false) {
logger.debug('terminating socket');
return ws.terminate();
}
ws.isAlive = false;
ws.ping('', false, true);
});
}, 30000);
ws.isAlive = true;
ws.on('pong', heartbeat);
});
After a few seconds all of the 30 something connected bots/clients are terminated (with log message "terminating socket"). I try to understand the ping-pong example but I think maybe I miss something?
UPD: After I took this part out of the wss.on('connection') and put it outside of this listener, the terminate thing doesn't happen any more.
const interval = setInterval(function ping() {
wss.clients.forEach(function each(ws) {
if (ws.isAlive === false) {
logger.debug('terminating socket');
return ws.terminate();
}
ws.isAlive = false;
ws.ping('', false, true);
});
}, 30000);
Any update here?
Yes. There doesn't seem to be any issue any more. The error is gone and can not be reproduced again. I don't even know what I have changed.
Ok nice. I'm closing then.
crazyyi
It should be outside of onconnection.
If you set it to inside of onconnection then it will be repeated for every socket connection.
Most helpful comment
crazyyi
It should be outside of onconnection.
If you set it to inside of onconnection then it will be repeated for every socket connection.