websocket connection is closing automatically - node.js

i have deployed websocket server on heroku and Everything is working good but if there is no transfer between server and client after a certain time the connection is closed. i don't know who is closing the connection server or client and how to resolve this issue.
here is my node.js client code-
const Websocket = require('ws');
var ws = new Websocket('https://secure-mountain-02060.herokuapp.com/');
ws.onmessage = function(event){
console.log(event.data);
}
ws.onclose = function(){
console.log('server close');
}

i found the solution server is closing the connection due to inactivity from client side.
for that we have to ping the server after a certain time that time can be very depending upon the server.
This is how i have solved if anyone needs.
const Websocket = require('ws');
var ws = new Websocket('https://secure-mountain-02060.herokuapp.com/');
function noop() {}
ws.onmessage = function(event){
console.log(event.data);
}
ws.onclose = function(){
console.log('server close');
}
const ping = function() {
ws.ping(noop);
}
setInterval(ping, 30000);

Related

Close createWebsocketStream without closing the websocket connection (node, ws)

I have been testing sending files over websocket from a client to server using the createWebsocketStream function from ws library like so:
client server
readFileStream ---> WebSocketStream ---> writeFileStream
It works insomuch as I can send even large files successfully, but when I try to close the duplex on the client side, it closes the whole websocket connection.
On the server-side, the WebsocketStream doesn't emit a close event so I can't signal based on that.
So I have two problems:
I can't start and end a duplex websocketstream on the same persistent websocket connection. To workaround this I fork a new websocket connection for streaming properties, but this kind of feels like a hack. If I understand correctly, this is because the duplex is a wrapper around the ws connection and is by design, but I would appreciate a sanity check on that.
The websocketstream doesn't emit a close event so I can't signal the filewrite stream to end based on that.
Is this by design? Is it not possible to start and end a duplex stream on the same ws connection?
If it helps, here is what I have working: I end the writeFileStream based on a ws connection closure:
server:
//server.js
const WebSocket = require('ws');
const fs = require('fs');
const wsserver = new WebSocket.Server({ port: 8080 });
const destinationFileStream = fs.createWriteStream('./bar');
wsserver.on('connection', function connection(ws) {
console.log("client connected");
duplex = WebSocket.createWebSocketStream(ws);
duplex.on('data', function(data){
destinationFileStream.write(data);
});
duplex.on('close', function(){ //<----------i want to put it here but this never triggers
console.log("the duplex channel has closed")
});
ws.on('close', function(){
console.log("websocket has closed")
destinationFileStream.end(); //<----------instead I have to put it here :(
});
destinationFileStream.on('close', function(){
console.log("file has been written successfully")
})
});
client:
//client.js
const WebSocket = require('ws');
const fs = require('fs');
// connect to the server for normal communication
const ws = new WebSocket('ws://localhost:8080');
const readFileStream = fs.createReadStream('/home/ubuntu/Downloads/atom-amd64.deb')
ws.on('open', function(){
// fork a NEW connection called wsstream with duplex properties so we can maintain a normal message channel here
var wsstream = new WebSocket('ws://localhost:8080');
var duplex = WebSocket.createWebSocketStream(wsstream, { emitClose: true });
readFileStream.on('data', function(data){
console.log('reading file stream')
duplex.write(data);
});
readFileStream.on('close', function(){
console.log("file has been read successfully")
duplex.end(); // <--- this triggers the wsstream.on('close') function
});
duplex.on('close', function(){ // <- this never fires because there's no close event
console.log("the duplex channel has closed")
});
wsstream.on('close', function(){
console.log("the wsstream has closed") // <-- closing the duplex channel closes the whole wsstream connection
});
// more functions below for the regular ws connection
});
p.s. sorry for code quality! I only started learning last week.

client undefined in websocket server

when i print client in console logconsole.log(client ${client}); it shows undefined.
I think i should do something in my client code but don't know what.
Server code -
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws, request, client) {
console.log(`client ${client}`);
ws.on('message', function message(msg) {
console.log(`Received message ${msg}`);
});
});
client code-
const Websocket = require('ws');
const ws = new Websocket('ws://localhost:8081');
function noop() {}
ws.on("message", function(event){
console.log(event);
});
const ping = function() {
ws.ping(noop);
}
setInterval(ping, 30000);
ws doesn't support client out of the box.
See: https://www.npmjs.com/package/ws#client-authentication
the gist of it is that you need to use an HTTP server to listen to any connections (not using ws to listen) and "manual" emit the connection event with additional data (like client).

node.js - issue with faye-websocket-node as client and sockjs-node as server

I'm trying to use faye-websocket-node ^0.11.0 as client, sockjs-node 0.3.18 as server, please refer to below client/server code
Issue:
if client and server prefix matchs, like below code prefix = /hello, client will throw Error during WebSocket handshake: Unexpected response code: 200
I tried using prefix = / on the server, this time there won't be any error message, but there's no connection open, no message printed from either client or server on open or on connection code
Question:
How to use faye-websocket-node as client, sockjs-node as server, and have them communicate via websock using node.js?
Thanks!
client code:
var WebSocket = require('faye-websocket'),
ws = new WebSocket.Client('ws://127.0.0.1:8888/hello');
ws.on('open', function(event) {
console.log('open');
ws.send('Hello, world!');
});
ws.on('message', function(event) {
console.log('message', event.data);
});
ws.on('close', function(event) {
console.log('close', event.code, event.reason);
ws = null;
});
ws.on('error', function(event){
console.log('error', event.message);
});
server code:
var sockjs = require('sockjs');
var http = require('http');
var sockjsServer = sockjs.createServer({
sockjs_url: '//d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.min.js'
});
sockjsServer.on('connection', function(conn) {
console.log('on connection');
conn.on('data', function(msg) {
console.log('\nRECV:'+msg);
});
});
var server = http.createServer();
sockjsServer.installHandlers(server, {prefix:'/hello'});
server.listen(8888, '0.0.0.0');
I raised ticket#229, answer from sockjs-node:
You cannot use faye-websocket directly as SockJS utilizes additional framing. You can do one of two things:
1. Use the "raw" endpoint as documented in the README: https://github.com/sockjs/sockjs-node#connecting-to-sockjs-node-without-the-client
2. Use sockjs-client from Node.js! Client versions >= 1.0 support usage directly from Node.

Websockets in NodeJS. Calling WebSocketServer from server-side WebSocket client

I have a NodeJS web app running. I have a WebSocketServer running. I can communicate with my app via a WebSocket connection made from my javascript on the client machine fine. Here's the nodejs server-side code snippet of relevance:
var WebSocket = require('ws');
var WebSocketServer = require('ws').Server;
var server = app.listen(process.env.VCAP_APP_PORT || 3000, function () {
console.log('Server started on port: ' + server.address().port);
});
wss.on('connection', function (ws) {
ws.on('message', function (message, flags) {
if (flags.binary) {
var value1 = message.readDoubleLE(0);
var value2 = message.readInt16LE(8);
var value3 = message.readInt8(10);
//message.writeDoubleLE(8.5,0);
ws.send(message, {
binary: true
});
} else {
if (message == "injest") {
ws.send("requested: " + message);
} else if (message == "something") {
wss.clients[0].send('server side initiated call');
} else {
ws.send("received text: " + message);
}
}
});
// ws.send('something'); // Sent when connection opened.
});
So you see, all very simple.
Here 's my problem. How can I access this WebServer from the NodeJS code of the server-side app itself?
I tried the below:
var ws = new WebSocket("ws://localhost:443");
ws.on('message', function (message) {
wss.clients[0].send('server side initiated call 1 ');
});
ws.on('close', function (code) {
wss.clients[0].send('server side initiated call 2 ');
});
ws.on('error', function (error) {
wss.clients[0].send(error.toString());
});
ws.send("k");
The error function is triggered with ECONNREFUSED 127.0.0.1:443.
I specified no port when I set the server up. If I do then the calls to the server from my client html page fail.
So in brief how can I set up a WebSocket client in NodeJS to access a WebSocketServer created in that app?
Do not use localhost. Substitute the 127.0.0.1 for it.
Instantiate the Server
let WebSocketServer = require("ws").Server;
let ws = new WebSocketServer({port: 9090});
ws.on('connection', function (ws) {
console.log(nHelp.chalk.red.bold('Server WebSocket was connected.'));
// Add the listener for that particular websocket connection instance.
ws.on('message', function (data) {
//code goes here for what you need
});
ws.on('close', function () {
console.log('websocket connection closed!');
});
});
You can open other ports and routes (example for Express) in the same file, or other ports for WS as well btw.
The above is not code for Secure WS server for TLS. that is a bit different.

How does one properly shutdown socket.io / websocket-client?

I'm trying to create a test using LearnBoost's socket.io and the node-websocket-client. Communication between the client and server work great. After all communication is done, I close both the client and the server. Yet the program hangs, waiting on some unknown callback. Two questions:
What is the following program waiting for?
Is there a tool for diagnosing outstanding callbacks in node programs?
var connect = require('connect'),
io = require('socket.io'),
WebSocket = require('websocket-client').WebSocket;
var port = 7111;
var server = connect.createServer();
var socket = io.listen(server);
socket.on('connection', function(client) {
client.send('Welcome!');
client.on('message', function(message) {
console.log(message);
});
client.on('disconnect', function() {
console.log('closing');
server.close();
});
});
server.listen(port, function() {
var ws = new WebSocket('ws://localhost:' + port + '/socket.io/websocket');
ws.onmessage = function(message) {
console.log(message.data);
};
setTimeout(function() {
ws.send('~m~3~m~Yo!');
ws.close();
}, 10);
});
EDIT: changed the variable name of the WebSocket to ws to avoid confusion
var socket = io.listen(server);
You've created a socket on a port. You've never closed it.
socket.server.close() closes your (socket.io) socket.
When in doubt read the socket.io github examples
socket.server === server It's the server you pass in, in the liste statement so it's closed. I'm not sure what it's waiting for.
Below a way to shutdown all the connections and be able to run multiple expresso tests (using socket.io and socket.io-client).
The solution is tricky and buggy but works on 0.8.5. The main problem is regarding the library to use websockets (node-websocket-client).
Currently, on socket.io, the OS contributors have patched the websocket client. So, we must do the same on our socket.io-client npm package to be able to use finishClose method on the socket client side. Socket.io-client uses the websocket library as npm package, so you must find the file (websocket.js) and substitute it with the same on socket.io.
Afterwards, you could use finishClose method to ensure the connections are closed and with some custom server/client socket settings, the tests will run correctly.
var io = require("socket.io").listen(port);
io.set('close timeout', .2);
io.set('client store expiration', .2);
var client = require("socket.io-client").connect( "http://localhost", { port: port , 'reconnect': false, 'force new connection': true});
client.on('connect', function() {
client.disconnect();
});
client.on('disconnect', function() {
client.socket.transport.websocket.finishClose();
io.server.close();
});
io.server.on('close', function() {
setTimeout( function() {
done();
}, 500);
});
Hope, somebody can help.
The program is waiting because socket.io (server) is still listening for incoming connections. I don't know of any way to stop listening.

Resources