i try to implement cluster in my node app with socket.io. if i not using cluster everything is working good. but when i use cluster its occur following error in client browser.
WebSocket connection to 'ws://localhost:8000/socket.io/?EIO=3&transport=websocket&sid=Ff8LkaCbF5g92lKOAAAS' failed: Error during WebSocket
socket.js:2 POST http://localhost:8000/socket.io/?EIO=3&transport=polling&t=MAjySbD&sid=Ff8LkaCbF5g92lKOAAAS 400 (Bad Request)
here is server.js
var http = require('http');
var app = require('../app');
cluster = module.exports = require('cluster');
const numCPUs = require('os').cpus().length;
var server = http.createServer(app);
io = module.exports = require('socket.io').listen(server, {
pingTimeout: 7000,
pingInterval: 10000
});
io.set("transports", ["xhr-polling","websocket","polling"]);
if(cluster.isMaster){
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
var port = 8000;
var host = '0.0.0.0';
server.listen(port,host,function(){
log('server is running on ' + host +':'+port);
});
}
here is the client.js
var socket = io.connect('http://localhost:8000/dashboard',{transports: ['websocket']});
Check if you using express-status-monitor as a middleware on express, this makes http call on the first (request) handshake of WebSocket goes failed, or maybe another factor like proxy (nginx) or similar like that
Look here for more details about this error
Related
I have a 4 core CPU with 8 logical processors, which in this code creates 8 workers and 1 master process. When a socket connection is formed, it tends to connect to the last worker, CPU 8. Does using this method automatically add a Load Balancer, or would I need to add it in? Is there a way to test if the Load Balancer is working? I've tried to add 100s of clients, but they all connect to CPU 8 - not sure if it could be because there is barely any process handling in this instance
Simple Node.js Clustering
const os = require('os'),
cluster = require('cluster'),
cores = os.cpus();
var clusterCount = 0;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers
for (let i = 0; i < cores.length; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
}
else {
const http = require('http'),
express = require('express'),
socketio = require('socket.io'),
process = require('process');;
var cpu = cores[clusterCount];
var app = express();
var port = process.env.PORT || process.argv[2] || 8080;
var server = app.listen(port);
var io = socketio(server);
io.adapter(socketioRedis({ host: config.redis_host, port: config.redis_port }));
io.on('connection', (socket) => {
console.log(`User ${socket.id} connected to worker ${process.pid}`);
});
console.log(`Worker ${process.pid} started on port: ${port} | ${cpu.model}`);
clusterCount++;
}
It depends on a couple of points. https://nodejs.org/api/cluster.html#cluster_how_it_works
Does using this method automatically add a Load Balancer?
The master will handle the load balancing.
sure if it could be because there is barely any process handling in this instance
It might be that CPU 8 is not that busy and can still handle the load. There are two strategies which also depend on the OS you are using.
I have a few questions about configuring socket.io for my node.js application.
When requiring var socket = require('socket.io')( /* HERE */ ), do I need to input the port my server listens where the /* HERE */ is at?
Right below the above line, I have another require function, for a .js file that contains a few constants and a function (see below). When I try to refer to 'socket' in that file it says it's undefined. But since this line is below the require line for the socket.io middleware seen above, why does it say 'undefined'?
const numbers = '1234'
function asd(req,res,next) {
socket.emit('a')
}
module.exports = {
asd
}
For configuring client-side socket.io, I added this line:
var socket = io.connect('https://mydomain')
Do I need to say 'mydomain:port' or is 'mydomain' enough?
This is how you use socket.io
var http = require('http');
var express = require('express');
var path = require('path');
var app = http.createServer();
var io = require('socket.io')(app);
var port = 8081;
io.on('connection', function(socket){
socket.on('event1', function (data) {
console.log(data);
socket.emit('event2', { msg: 'delivered' });
});
});
app.listen(port);
Answer to your second question
Yes, you will need to specify the port you are using
<script src="socket.io.js"></script>
<script>
var socket = new io.Socket();
socket.connect('https://mydomain:8081')
socket.on('your_event',function() {
console.log('your_event receivid from the server');
});
</script>
Here socket will connect to port 8081
This is a simple server side code
var http = require('http');
var io = require('socket.io');
var port = 8081;
// Start the server at port 8081
var server = http.createServer();
server.listen(port);
var socket = io.listen(server);
// example listener
socket.on('event_2', function(client){
console.log('event_2 received');
});
// example emitter
socket.emit('event_1', { hello: 'world' });
I wrote a Web Socket server using socket.io, node-http2 and express in Node.js. The server works as intended, except for the fact that according to Chrome's DevTools socket.io's negotiation requests go through HTTP/1.1 (shown below). The "Protocol" column should be displaying h2 if the request was sent using HTTP/2.
This only happens in Chrome, other browsers use the correct protocol.
The server code (shortened):
var PORT = 8667,
config = require('./config'),
socketioServer = require('socket.io'),
app = express(),
https = require('http2'),
cors = require('cors');
app.use(cors(function(req, callback){
var corsOptions = { origin: false };
if (/^https:\/\/mlpvc-rr\.lc/.test(req.header('Origin')))
corsOptions.origin = true;
callback(null, corsOptions);
}));
app.get('/', function (req, res) {
res.sendStatus(403);
});
var server = https.createServer({
cert: fs.readFileSync(config.SSL_CERT),
key: fs.readFileSync(config.SSL_KEY),
}, app);
server.listen(PORT);
var io = socketioServer.listen(server);
// ...
Browser connection code:
var conn = io('https://ws.'+location.hostname+':8667/', { reconnectionDelay: 5000 });
conn.on('connect', function(){
console.log('[WS] Connected');
});
conn.on('disconnect',function(){
console.log('[WS] Disconnected');
});
Output of testssl.sh:
What do I need to change to make the socket.io requests go through HTTP/2?
A little bit late but with Express4 and Spdy (npm) is working great.
bin/www:
var app = require('../app');
var debug = require('debug')('gg:server');
var spdy = require('spdy');
var fs = require('fs');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var options = {
key: fs.readFileSync(__dirname + '/server.key'),
cert: fs.readFileSync(__dirname + '/server.crt')
}
var server = spdy.createServer(options, app);
var io = app.io
io.attach(server);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
...
app.js:
...
var app = express();
var io = app.io = require('socket.io')();
...
client screenshot:
As discussed in comments Chrome has recently stopped allowing the older NPN negotiation for HTTP/2 and insists on the newer ALPN protocol instead. See this article for more info: https://ma.ttias.be/day-google-chrome-disables-http2-nearly-everyone-may-31st-2016/
So you basically need Node.js to support ALPN which it looks as has only been added in v5 so far: https://github.com/nodejs/node/pull/2564 . An alternative would be to route your NodeJs calls through a webserver which is easier to upgrade OpenSSL (e.g. Nginx or Apache) to support HTTP/2 over ALPN.
You confirmed this was the issue by using the testssl.sh program which confirmed no ALPN support and the fact Firefox uses HTTP/2.
please look at the code below. It's a simple program in nodeJS.
Question is why disconnect is not printed? (If you uncomment setTimeout, problem is gone)
What is the real question?: Why can't I start socketIO client and server together and close a socket immediately after connection? What is the know-how regarding connections with socketIO?
"use strict";
var Promise = require("bluebird");
var socketio = require("socket.io");
var socketio_client = require("socket.io-client");
var http = require("http");
var port = 7457;
var hostandport = "http://localhost:" + port.toString();
var server = socketio.listen(port);
var client = socketio_client(hostandport);
server.sockets.on("connect", function (socket) {
console.log("connect");
socket.on("disconnect", function () {
console.log("disconnect");
});
//setTimeout(function() {
client.disconnect();
//}, 1000);
});
You have set up your server incorrectly, do this instead:
var server = require('http').createServer(handler);
var io = require('socket.io')(server);
io.on("connect", function (socket) {
console.log("connect");
socket.on("disconnect", function () {
console.log("disconnect");
});
//More importantly, you have done this part wrong,
//the rest of your code may be functional,
//but it does not adhere to what socket.io sets out in its own API
//(http://socket.io/docs/)
socket.disconnect();
});
In Socket.io there is no such thing as connection on server side and/or browser side. There is only one connection. If one of the sides closes it, then it is closed. So you can close it from Server using socket.disconnect()
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
setTimeout(function() {
socket.disconnect();
}, 1000);
});
Goto http://socket.io/get-started/chat/ for more clarifications.
I want to transfer a file with node.js using socket.io (socket.io-client) and delivery.
I tried to do this on server-side:
//// server.js
var socket = require('socket.io').listen(5000);
var dl = require('delivery');
var fs = require('fs');
socket.on('connect', function() {
log( "Sockets connected" );
delivery = dl.listen(socket);
delivery.connect();
delivery.on('delivery.connect',function(delivery){
delivery.send({
name: 'file1.zip',
path : './file1.zip'
});
delivery.on('send.success',function(file){
console.log('File sent successfully!');
});
});
});
And this on client-side:
//// client.js
var io = require('socket.io-client');
var dl = require('delivery');
var fs = require('fs');
var socket = io.connect('http://localhost:5000');
socket.on('connection', function(socket){
var delivery = dl.listen(socket);
delivery.on('receive.success',function(file){
fs.writeFile(file.name, file.buffer, function(err) {
if(err) {
console.log('File could not be saved: ' + err);
} else {
console.log('File ' + file.name + " saved");
};
});
});
});
On execution, there is no error, but it hangs.
Server-side:
$ node server.js
info - socket.io started
debug - client authorized
info - handshake authorized Bbzo928wAyTjDX8v06Ic
debug - setting request GET /socket.io/1/websocket/Bbzo928wAyTjDX8v06Ic
debug - set heartbeat interval for client Bbzo928wAyTjDX8v06Ic
debug - client authorized for
debug - websocket writing 1::
debug - emitting heartbeat for client Bbzo928wAyTjDX8v06Ic
debug - websocket writing 2::
debug - set heartbeat timeout for client Bbzo928wAyTjDX8v06Ic
debug - got heartbeat packet
debug - cleared heartbeat timeout for client Bbzo928wAyTjDX8v06Ic
debug - set heartbeat interval for client Bbzo928wAyTjDX8v06Ic
And on client-side there is no output:
$ node client.js
Do anyone know, what goes wrong?
First of all, the version of delivery in the NPM repository is out of date, and contains some bugs. You should install the latest version from GitHub:
$ npm install git+https://github.com/liamks/Delivery.js.git
Next, you're mixing up some client and server parts, specifically the events that each has to handle. This (somewhat, see below) works for me:
//// server.js
var io = require('socket.io').listen(5000);
var dl = require('delivery');
var fs = require('fs');
io.sockets.on('connection', function(socket) {
console.log('server: a new client connected');
var delivery = dl.listen(socket);
delivery.on('delivery.connect', function(delivery) {
delivery.send({
name: 'file1.zip',
path : './file1.zip'
});
delivery.on('send.success', function(file) {
console.log('File sent successfully!');
});
});
});
//// client.js
var io = require('socket.io-client');
var dl = require('delivery');
var fs = require('fs');
var socket = io.connect('http://localhost:5000');
socket.on('connect', function() {
console.log('client: connected to server');
var delivery = dl.listen(socket);
delivery.connect();
delivery.on('receive.success', function(file) {
// TODO: fs.writeFile(...);
});
});
However, it seems that the receive.success event is delivered to the client twice, at least for me. I'm not sure why (I'm not overly familiar with delivery).