Jump to content

Create a Cluster Server with Node.js and socket.IO


Dad72
 Share

Recommended Posts

What is a 40.50.60.20 

It is necessary that you use your server address

 

if you made it even http://40.50.60.20 go nowhere. You may have a problem with the server configuration. Your DNS can be. you are on a dedicated server?

 

try it with localhost. if you run the server on the machine directly SSH, localhost is ok.

Link to comment
Share on other sites

I used the address of the server instead of localhost because the client files are run on another PC that is not the server.

(40.50.60.20 is only an expample of server ip instead of localhost)

 

 

----------------------------------

Maybe is a problem with Cluster? (https://github.com/Unitech/pm2/issues/81)

 

RedisStore is a bit different (https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0#redisstore-changes)

 

--------------------------------

 

it seems that I have solved:
https://github.com/evilstudios/chat-example-cluster

Link to comment
Share on other sites

Ok it all works but I have a problem.

 

Passing an object as a variable( example pickInfo) in the server side gives me an error(using ent.encode(objet);).

 

Without ent.encode() gives me this error(maybe javascript/socket.io):

 

https://github.com/Automattic/socket.io/issues/1989

 

 

if anyone knows what is wrong or if there's another way to pass objects let me know, thanks.

Link to comment
Share on other sites

You are not forced to use 'ent'

 

Ok but without 'ent' gives me this error (i think javascript or socket.io) https://github.com/Automattic/socket.io/issues/1989

 

 

How have you resolved your problem exactly? I could fix the code here for other person.

 

I used this   https://github.com/evilstudios/chat-example-cluster/blob/master/index.js

 

There was an error with cluster.

Link to comment
Share on other sites

I find this way of doing bad. but maybe I can try to correct the server here.

 

On your server, it uses the number of manual workers, but if the processor of the machine is a 4 core, it could create more Workers (5) and I see that it does not detect what is the Master and What are the Workers.

 

and for erreur: You send too many thing with that server: pickInfo.pickedMesh

 

try pickInfo.pickedMesh.name

 

and client : sene.getMeshByName() for search the model

Link to comment
Share on other sites

 

I find this way of doing bad. but maybe I can try to correct the server here.
 
On your server, it uses the number of manual workers, but if the processor of the machine is a 4 core, it could create more Workers (5) and I see that it does not detect what is the Master and What are the Workers.
 
and for erreur: You send too many thing with that server: pickInfo.pickedMesh
 
try pickInfo.pickedMesh.name
 
and client : sene.getMeshByName() for search the model

 

Ok.

yes it seems to work perfectly!

 

I made some changes on the server.  This should work better for 'Redis'

I tried with your changes but gives me an error:

http://s23.postimg.org/tixearg3f/Cattura2.png

 

I think that the module "redis" there isn't in the socket.io but there is this: https://www.npmjs.com/package/socket.io-redis

Link to comment
Share on other sites

I have updated the server going to check with the block try and catch()

I hope it will work. Otherwise try to correct and send the correction. because I only tests locally now. Thanks.

I tried but gives me an error: Cannot find module 'socket.io/lib/sores/redis'.

 

I think you are using an older version of socket.io.

Link to comment
Share on other sites

 

Yes you reasons I reinstall everything. everything is up to date now.
I fixe the server that now works and I bring some small improvement.
I think it'll work for you.  :D

 

Ok i tried but but with your changes gives me this error (client side): 

 

WebSocket connection to 'ws://serverip:9520/socket.io/?EIO=3&transport=websocket&sid=YcKquHdjmXK1_nLoAAAA' failed: Connection closed before receiving a handshake response

Link to comment
Share on other sites

It works with me. you may be missing something. I updated and I have no error.

 

try http:// and no ws: in io.connect()

 

I've updated the first post with some addition and I add the most complete client part.
I also add a module to run the server in the background (Run as a service). "forever"
Link to comment
Share on other sites

  • 2 weeks later...
No it's not really that. It is a server (of game) running on your hosting server (server web) which allows any clients that connect to your game (web) to receive information from the server (of game).

Take the example of a cat. there is one side the server that receives information and transmits everything users connect to the chat.

But it can also allow viewing in real time the position of the players in an MMORPG type of game, MMOFPS ...

Link to comment
Share on other sites

  • 2 months later...

Bad solution. For example

socket.on('disconnect', function(socket){  socket.broadcast.emit('disconnect_client', socket.pseudo);  console.log('The player '+socket.pseudo+' is disconnect');});

this event will be raised only for a worker where a client has connected, but all other workers will not be handle this event, therefore clients are connected to other workers  will not be notified that some client disconnected.

Link to comment
Share on other sites

  • 1 month later...

Sorry for the late reply. I did not see your message xfg  :ph34r:

You have reasons disconnect is a bad idea, it create a bug, because the variable socket.pseudo no longer exists. I updated the post.  :)
 
Thank you xfg
Link to comment
Share on other sites

  • 2 months later...

I have update the server to make it more efficient and add a very large number of simultaneous connection. but depends also of the server on which it is executed.

 

I add this in cluster.Worker:

var http = require('http');http.globalAgent.maxSockets = Infinity;//andsocket.setNoDelay(true);

and for start i add "--nouse-idle-notification --expose-gc":

forever start /MIN redis-server.exeforever start /MIN node --nouse-idle-notification --expose-gc serveur.js 
This allows to significantly increase server performance and pass the barrier of limitations. It seems that the saturation limit is 25,000 simultaneous connections. Good after there are the players' positions and other data to send to the server, but if you for example have 416 players (25000 / 60FPS) I guess it's widely as possible, although it is necessary to control the packets that are sent to make light.
 
Me it seem to me enormous. But if I believe what I li tested by other developers, that's it. It is still very fuzzy for me without testing. When I entant such as SecondLife is 12 players per server, I not understand much more.
Link to comment
Share on other sites

  • 2 months later...
  • 6 months later...

I hate to necropost, but @Dad72 your server code ( which I translated into English btw ), is not working with the latest node.js... I installed all the dependencies & have turned on the Redis Server, but when I go to localhost:8080, I get : 

TypeError: res.emitfile is not a function

var cluster = require('cluster');
	var _portSocket = 8080;
	var _portRedis = 6379;
	var _HostRedis = 'localhost';
	if (cluster.isMaster) {
	    var server = require('http').createServer();
	    var socketIO = require('socket.io').listen(server);
	    var redis = require('socket.io-redis');
	    socketIO.adapter
	        (
	        redis
	            (
	            {
	                host
	                :
	                _HostRedis,
	                port
	                :
	                _portRedis
	            }
	            )
	        );
	    var numberOfCPUs = require('os').cpus().length;
	    for (var i = 0; i < numberOfCPUs; i++) {
	        cluster.fork();
	    }
	    cluster.on
	        (
	        'fork',
	        function (worker) {
	            console.log('Worker %s Created', worker.id);
	        }
	        );
	    cluster.on
	        (
	        'online',
	        function (worker) {
	            console.log('Worker %s Online!', worker.id);
	        }
	        );
	    cluster.on
	        (
	        'listening',
	        function (worker, addr) {
	            console.log
	                (
	                'Worker %s listening on %s:%d',
	                worker.id,
	                addr.address,
	                addr.port
	                );
	        }
	        );
	    cluster.on
	        (
	        'disconnect',
	        function (worker) {
	            console.log('Worker %s went Offline . . .', worker.id);
	        }
	        );
	    cluster.on
	        (
	        'exit',
	        function (worker, code, signal) {
	            console.log
	                (
	                'Worker %s has died ( %s )',
	                worker.id,
	                signal
	                ||
	                code
	                );
	            if (!worker.exitedAfterDisconnect) {
	                console.log('New worker { %s } created', worker.id);
	                cluster.fork();
	            }
	        }
	        );
	}
	if (cluster.isWorker) {
	    var http = require('http');
	    http.globalAgent.maxSockets = Infinity;
	    var app = require('express')();
	    var ent = require('ent');
	    var fs = require('fs');
	    var server = http.createServer(app).listen(_portSocket);
	    var socketIO = require('socket.io').listen(server);
	    var redis = require('socket.io-redis');
	    socketIO.adapter
	        (
	        redis
	            (
	            {
	                host
	                :
	                _HostRedis,
	                port
	                :
	                _portRedis
	            }
	            )
	        );
	    app.get
	        (
	        '/',
	        function (req, res) {
	            res.emitfile
	                (
	                __dirname
	                +
	                '/interface.php'
	                );
	        }
	        );
	    socketIO.sockets.on
	        (
	        'connection',
	        function (socket, pseudo) {
	            socket.setNoDelay(true);
	            socket.on
	                (
	                'new_client',
	                function (pseudo) {
	                    pseudo = ent.encode(pseudo);
	                    socket.pseudo = pseudo;
	                    try {
	                        socket.broadcast.to(socket.room).emit
	                            (
	                            'new_client',
	                            pseudo
	                            );
	                    }
	                    catch (e) {
	                        socket.to(socket.room).emit
	                            (
	                            'new_client',
	                            pseudo
	                            );
	                    }
	                    console.log
	                        (
	                        'User :: ' + socket.pseudo + ' has come Online!'
	                        );
	                }
	                );
	            socket.on
	                (
	                'message',
	                function (data) {
	                    socket.broadcast.to(socket.room).emit('dispatch', data);
	                }
	                );
	            socket.on
	                (
	                'exit',
	                function (data) {
	                    socket.close();
	                }
	                );
	            socket.on
	                (
	                'room',
	                function (newroom) {
	                    socket.room = newroom;
	                    socket.join(newroom);
	                    console.log
	                        (
	                        'User :: ' + socket.pseudo + ' has rejoined the { ' + socket.room + ' } room!'
	                        );
	                    socket.broadcast.to(socket.room).emit
	                        (
	                        'dispatch',
	                        'User :: ' + socket.pseudo + ' has rejoined the { ' + socket.room + ' } room!'
	                        );
	                }
	                );
	        }
	        );
	}

I'm also trying to HolePunch through UDP so I can use my Galaxy S6 Phone as a hosting Server that the outside world can automatically connect to via the client.

Thanks! <3

Link to comment
Share on other sites

Try to comment. It may not be helpful.

/*
app.get
	        (
	        '/',
	        function (req, res) {
	            res.emitfile
	                (
	                __dirname
	                +
	                '/interface.php'
	                );
	        }
	        );
*/

Otherwise i think it's emitFile (But I'm not sure. This may have changed with the new version of nodeJS. I have not updated the code that dates a can.)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...