Node js with express return connection closed before receiving a handshake response - node.js

I have a socket running in nodejs and using this socket in html page this is working fine and some times I'm receiving the error on developer console as like
failed: Connection closed before receiving a handshake response. In this time my update not getting reflect on the user screen. Actually whenever the changes updated in admin screen I written the login in laravel to store this values into the redis and I have used the laravel event broadcast and in node js socket.io read the redis value change and push the values into the user screens.
I have code in laravel as like,
Laravel Controller,
public function updatecommoditygroup(Request $request)
{
$request_data = array();
parse_str($request, $request_data);
app('redis')->set("ssahaitrdcommoditydata", json_encode($request_data['commodity']));
event(new SSAHAITRDCommodityUpdates($request_data['commodity']));
}
In this above controller when the api call receives just store the values into this redis key and broadcast the event.
In my event class,
public $updatedata;
public function __construct($updatedata)
{
$this->updatedata = $updatedata;
}
public function broadcastOn()
{
return ['ssahaitrdupdatecommodity'];
}
Finally I have written my socket.io file as like below,
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis({ port: 6379 } );
redis.subscribe('ssahaitrdupdatecommodity', function(err, count) {
});
io.on('connection', function(socket) {
console.log('A client connected');
});
redis.on('pmessage', function(subscribed, channel, data) {
data = JSON.parse(data);
io.emit(channel + ':' + data.event, data.data);
});
redis.on('message', function(channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
http.listen(3001, function(){
console.log('Listening on Port 3001');
});
When I have update the data from admin I'm passing to laravel controller, and controller will store the received data into redis database and pass to event broadcast.And event broadcast pass the values to socket server and socket server push the data whenever the redis key get change to client page.
In client page I have written the code as like below,
<script src="../assets/js/socket.io.js"></script>
var socket = io('http://ip:3001/');
socket.on("novnathupdatecommodity:App\\Events\\NOVNATHCommodityUpdates", function(data){
//received data processing in client
});
Everything working fine in most of the time and some times issue facing like
**VM35846 socket.io.js:7 WebSocket connection to 'ws://host:3001/socket.io/?EIO=3&transport=websocket&sid=p8EsriJGGCemaon3ASuh' failed: Connection closed before receiving a handshake response**
By this issue user page not getting update with new data. Could you please anyone help me to solve this issue and give the best solution for this issue.

I think this is because your socket connection timeout.
new io({
path:,
serveClient:,
orgins:,
pingTimeout:,
pingInterval:
});
The above is the socket configuration. If you are not configuring socket sometime it behaves strangely. I do not know the core reason, but i too have faced similar issues that implementing the socket configuration solved it.
Socket.io Server
Similar configuration should be done on the client side. There is an option of timeout in client side
Socket.io Client
For example.
Say this is your front-end code
You connect to the socket server using the following command:
io('http://ip:3001', { path: '/demo/socket' });
In your server side when creating the connection:
const io = require("socket.io");
const socket = new io({
path: "/demo/socket",
serveClient: false /*whether to serve the client files (true/false)*/,
orgins: "*" /*Supports cross orgine i.e) it helps to work in different browser*/,
pingTimeout: 6000 /*how many ms the connection needs to be opened before we receive a ping from client i.e) If the client/ front end doesnt send a ping to the server for x amount of ms the connection will be closed in the server end for that specific client*/,
pingInterval: 6000 /* how many ms before sending a new ping packet */
});
socket.listen(http);
Note:
To avoid complication start you http server first and then start you sockets.
There are other options available, but the above are the most common ones.
I am just describing what i see in the socket.io document available in github.socket_config. Hope this helps

Related

Socket IO doesn't get emitted from client - Node JS

I am working on Socket IO, the connection between the client and the server is established successfully. I am facing two problems:
1 - When the initial connection is made between the client and the server, the socket.client.id on server and socket.id on client side, both are the same, but when I refresh the client page, the id of the client changes to other one, but on the server it is still the same. Does it makes any issue / problem while communicating with the server or even with the client using sockets, while not having the same ids ? or does the id on the server get changed when the client page is refreshed ?
2 - On the initial connection establishment the socket passes a messages, using socket.emit() from server and receives as socket.on() on client. But when I try to emit anything from client it doesn't get received on server.
Socket Connections
function Globals() {
this.socketConnection = async function() {
let p = new Promise(function(res, rej) {
io.on("connection", function(socket) {
if (socket.connected) {
res(socket);
} else {
rej("Socket Connection Error !");
}
})
})
return await p;
}
}
new Globals().socketConnection().then(function(soc) {
console.log(soc.client.id);
socket = soc;
soc.emit("Hi");
soc.on("Nady", function() {
console.log("I am called");
})
})
Client Side Connection
function Globals() {
this.socketConnection = async function() {
var socket = io('http://localhost:8080');
let p = new Promise(function(res, rej) {
socket.on('connect', function() {
if (socket.connected) {
console.log(socket.id);
res(socket);
}
})
})
return await p;
}
}
var socket;
new App().socketConnection().then(function(s) {
socket = s;
});
function ScrapJobs() {
var socket;
new App().socketConnection().then(function(s) {
socket = s;
});
var _this = this;
this.attachListeners = function() {
qs("#init-scrap").ev("click", _this.startScrapping);
}
this.startScrapping = function() {
console.log("I am cliced");
socket.on("Hi", function() {
console.log("Hi Nadeem");
})
socket.emit("Nady");
}
}
When the initial connection is made between the client and the server, the socket.client.id on server and socket.id on client side, both are the same, but when I refresh the client page, the id of the client changes to other one, but on the server it is still the same. Does it makes any issue
The client side socket.id value is set on the client socket object after the connect event is received and is updated (e.g. modified) upon a reconnect event.
It appears that the socket.io infrastructure will keep them the same on client and server. If the client disconnects and then reconnects, there will be a new connection with a new id on both client and server. It is possible you are attempting to hang onto the old socket object on the server after the client has disconnected it (we can't really see enough of your server code to evaluate that).
On the initial connection establishment the socket passes a messages, using socket.emit() from server and receives as socket.on() on client. But when I try to emit anything from client it doesn't get received on server.
You'd have to show us a reproducible case. This does not happen if you are coding things correctly. I would guess that you do not have the right listeners for messages on the right socket in order to see the messages you are sending. I promise you that sending a message from client to server works just fine when implemented properly.
A general comment about your code. Both code blocks you show appear to be stuffing a socket object into a higher scoped (or perhaps even global) variable. That is likely part the cause of your problem because that socket object can become dead if the client reconnects for any reason. Plus putting any sort of socket object into a global or module level variable makes your server only capable of serving one client - it's simply not how you design multi-client servers.

Combining Nodejs Net socket and Socket IO

I have a windows application (Built on C# as windows service) that sends data to NodeJs Net Socket, So since Socket.IO helps making a Web Application a live one , without the need of reload. How can i allow Socket.IO stream the received data from NodeJs Net Socket to the Web Application , in the exact moment the Net Socket receives data from C#?
So in the code that receives the socket data from C#:
var net = require('net');
net.createServer(function (socket) {
socket.on('data', function (data) {
broadcast(socket.name + "> \n" + data + " \n", socket);
socket.end("<EOF>");
//send data to web interface , does it work that way?
//SomeFooToSendDataToWebApp(Data)
});
});
Further more for the Socket.IO i have those lines , which i cant really figure out how to deal with them:
//Should it listen to net socket or web socket?
server.listen(8080);
// Loading socket.io
var io = require('socket.io').listen(server);
// It works but only for one request
io.sockets.on('connection', function (socket2) {
socket2.emit('message' , 'Message Text');
});
P.S: I am new to nodejs & socket.io , so if its possible as well to explain their behavior.
Edit 1 : My Front End Javascript to check it if it has any problems:
//for now it listens to http port , which Socket.IO listens to
var socket = io.connect('http://localhost:8080');
var myElement = document.getElementById("news");
socket.on('message', function(message) {
document.getElementById("news").innerHTML = message;
})
Edit 2 : Did follow jfriend00's answer as it seems my previous code tries were trying to send messages to an unknown socket, i only added this since i needed it to be sent to all the connected clients , so only one line fixed it !
socket.on('data', function (data) {
broadcast(socket.name + "> \n" + data + " \n", socket);
socket.end("<EOF>");
//send data to web interface , does it work that way?
//The Added code here:
io.emit('message',data + " more string");
});
It's a bit hard to tell exactly what you're asking.
If you have some data you want to send to all connected socket.io clients (no matter where the data came from), then you can do that with:
io.emit("someMessage", dataToSend);
If you want to send to only one specific connected client, then you have to somehow get the socket object for that specific client and then do:
socket.emit("someMessage", dataToSend);
How you get the specific socket object for the desired connected client depends entirely upon how your app works and how you know which client it is. Every socket connection on the server has a socket.id associated with it. In some cases, server code uses that id to keep track of a given client (such as putting the id in the session or saving it in some other server-side data). If you have the id for a socket, you can get to the socket with the .to() method such as:
io.to(someId).emit("someMessage", dataToSend);
Your question asked about how you send data received from some C# service over a normal TCP socket. As far as sending it to a socket client, it does not matter at all where the data came from or how you received it. Once you have the data in some Javascript variable, it's all the same from there whether it came from a file, from an http request, from an incoming TCP connection in your C# service, etc... It's just data you want to send.
You can try the following, simple server:
const io = require('socket.io')(8080);
io.on('connection', socket => {
console.log('client connected');
socket.on('data', data => {
io.emit('message', data);
});
});
console.log('server started at port 8080');
It should work if I understand the problem correctly.
And maybe document.getElementById("news").innerHTML += message; in the html client code to see what really happens there?
socket2 means your client which just connected. So you can store these connections to send data to them (helpful for broadcast).
If you get data from windows service via some polling mechanism, on this step you can send this message to your connected clients. So keep your connections in a array to send specific messages each client afterwards

Socket.IO, SSL Problems With cloudflare

I'm having a socket.io app that basically receives signals from a frontend in order to kill and start a new ffmpeg process (based on .spawn()).
Everything works like expected, but often I get a 525 error from cloudflare. The error message is: Cloudflare is unable to establish an SSL connection to the origin server.
It works like 9 out of 10 times.I noticed that more of these errors pop up whenever a kill + spawn is done. Could it be the case that something block the event loop and because of this blocks all incoming requests and cloudflare logs these as a handshake failed error?
Contacting cloudflare support gives me back this info (this is the request they do to my server):
Time id host message upstream
2017-08-16T09:14:24.000Z 38f34880faf04433 xxxxxx.com:2096 peer closed connection in SSL handshake while SSL handshaking to upstream https://xxx.xxx.xxx.xxx:2096/socket.io/?EIO=3&transport=polling&t=LtgKens
I'm debugging for some time now, but can't seem to find a solutions myself.
This is how I initialize my socketIO server.
/**
* Start the socket server
*/
var startSocketIO = function() {
var ssl_options = {
key: fs.readFileSync(sslConfig.keyFile, 'utf8'),
cert: fs.readFileSync(sslConfig.certificateFile, 'utf8')
};
self.app = require('https').createServer(ssl_options, express);
self.io = require('socket.io')(self.app);
self.io.set('transports', ['websocket', 'polling']);
self.app.listen(2096, function() {
console.log('Socket.IO Started on port 2096');
});
};
This is the listener code on the server side
this.io.on('connection', function (socket) {
console.log('new connection');
/**
* Connection to the room
*/
socket.on('changeVideo', function (data) {
//Send to start.js and start.js will kill the ffmpeg process and
start a new one
socket.emit('changeVideo');
});
});
Another thing that I observer while debugging (I only got this a few times):
The text new connection displayed on the server and the connected client emits the changevideo event but nothing happens on the server side instead the client just
keeps reconnecting.
This is a simplified version of the nodejs code. If you have more questions, just let me know.
Thanks!

Nodejs Error: This socket has been ended by the other party

I have setup a simple server and client, however whenever I close the client, it seems not possible to reconnect. Here's my client:
const net = require('net');
var client = net.connect({port: 8080, host: '127.0.0.1'});
var response = '';
// events
client.on('data', function(chunk) { response += chunk });
client.on('end', function() {
console.log(response);
client.end()
});
// main execution
client.write('test');
And here's my server:
const net = require('net');
var server = net.createServer();
server.listen(8080, '127.0.0.1');
server.on('connection', function(sock) {
sock.on('data', function(chunk) {
sock.write('test received');
sock.end();
});
});
This is just outline code representing my issue. When I execute my client the first time, everything works correctly. However, when I execute it again, the server outputs the error mentioned in the title and crashes. The same happens if I remove 'client.end()' and instead Ctrl+C out of the client program to cause it to end.
My understanding of sockets is that they represent endpoints in a stream between the client and the server. When that stream is no longer necessary (i.e, when the client does what it needs to do), I want that stream to be completely removed. I would think that calling end() on both the client and server endpoints of that single stream would achieve this, like sending two FIN messages, but as explained it does not. The reasons I want to do this are so: (a) the client file will actually finish execution and (b) the server will no longer have its socket endpoint of that stream in its system/waste resources listening to it.
Any insight into the source of my problem would be appreciated.
You should use the 'connect' event on the client-side to be sure that you perform requests only when your socket is ready. So, in the callback on the event, you can invoke write() function.
You can check if socket is not destroyed before writing.
if (!socket.destroyed) socket.write("something");
Your server only closes the socket when data is received, and your client never sends any.

Socket.io with multiple Node.js hosts, emit to all clients

I am new to Socket.io and trying to get my head around the best approach to solve this issue.
We have four instances of a Node.js app running behind a load balancer.
What I am trying to achieve is for another app to POST some data to the load balancer URL which will hand if off to one of the instances.
The receiving instance will store the data, then use Socket.io to emit the data to the connected clients.
The issue is that browser/client can only be connected to a single instance at one time.
I am trying to determine if there is a way to emit to all clients at once?
Or have the clients connect to multiple servers using io.connect?
Or is this a case for Redis?
Publish/Subscribe is what you need here. Redis will give you the functionality your looking for out of the box. You just need to create a redis client and subscribe to an update channel on each of your app server nodes. Then, publish the update when a POST is successful (or whatever). Finally, have the redis client subscribe to the update chanel and on message emit a socketio event:
(truncated for brevity)
var express = require('express')
, socketio = require('socket.io')
, redis = require('redis')
, rc = redis.createClient()
;
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
server.listen(3000);
app.post('/targets', function(req, res){
rc.publish('update', res.body);
});
rc.on('connect', function(){
// subscribe to the update channel
rc.subscribe('update');
});
rc.on('message', function(channel, msg){
// util.log('Channel: ' + channel + ' msg: ' + msg);
var msg = JSON.parse(msg);
io.sockets.in('update').emit('message', {
channel: channel,
msg: msg
});
});
Then in the JS app, listen for that emitted message:
socket.on('message', function(data){
debugger;
// do something with the updated data
});
Of course, introducing this new Redis Server adds another single point of failure. A more robust implementation may use something like a message broker with AMQP or ZeroMQ or some similar networking library which provides pub/sub capabilities.

Resources