Using Meteor and socket.io together - node.js

I am newbie about Meteor.
I am developing a realtime multiplayer game. I want to implement everything about the game but game engine states with Meteor. For example chat messages, available game rooms, invitations, online members etc. I want to make those functionalities withMeteor.
But I want to implement game states manually without Meteor with socket.io. Because, the game is real time and every 45 msec(in my architecture), game states will be streaming to the clients and I think Meteor is not for this and not flexiable. So I developed multiplayer concept and synchronising clients and server with socket.io. There is no problem about it.
I want to use Meteor and socket.io both and together. I tried to implement it. I installed socket.io with npm inside .meteor/local/build/programs/server/app under my meteor app. After that I include require statement on server side Meteor startup;
Meteor.startup(function () {
var require = Npm.require;
var sio = require('socket.io')
var socketIO = sio.listen(this.http)
socketIO.configure(function () {
socketIO.set('log level', 0);
socketIO.set('authorization', function (handshakeData, callback) {
callback(null, true); // error first callback style
});
socketIO.set("transports", ["xhr-polling"]);
socketIO.set("polling duration", 30);
});
socketIO.sockets.on('connection', function (client) {
console.log(client.id + ' is connected')
client.on('disconnect', function () {
console.log(client.id + ' is diconnected')
});
})})
And I put the connection statement on client side Meteor startup;
Meteor.startup(function () {
socket = io.connect();
socket.on('connect', function () {
console.log('connecting');
});
})
On client side, io variable is not defined error is occurred. This is seen to me that,Meteor does not import client side socket.io.js on client side. So I tried to put socket.io.js manually under clients folder to load it on client side. This is not good way I know, I should not do this. But, even I do and client loads it, there is another client side error about transport variable of io for the statement;
io.transports.push('xhr-polling');
It says that Uncaught TypeError: Cannot call method 'push' of undefined. Somehow, client side socket.io.js can not be loaded properly.
I could not find an example for usage of Meteor and socket.io together. Is there a simple way to use them both together?
Thank you!

Related

Socket.io client in NodeJS

I want to build a microservice infrastructure with nodejs services and a master service, the communication between these services should happen via socket.io, i've setup my socket.io server, but their browser client (socket.io-client) is not working in nodejs (i guess it uses some browser only APIs). Is there a way to create a nodejs socket.io (NOT WEBSOCKETS) client?
EDIT
My client side code:
import { io } from "socket.io-client";
const socket = io("127.0.0.1:3000");
socket.on("connect", () => {
console.log(socket.id);
});
socket.on("disconnect", () => {
console.log(socket.id);
});
My server side code:
import { Server } from "socket.io";
const io = new Server();
io.on("connection", (socket) => {
console.log(socket)
});
io.listen(3000);
Both are written in typescript, the package versions are:
socket.io: ^4.4.0
socket.io-client: ^4.4.0
The Problem is, that i don't get any logs in my console, so i think there is something wrong with client, because socket.io does not mention node in there client side compatiblity graph.
The problem is that you have to pass a valid URL here:
const socket = io("127.0.0.1:3000");
I have no idea why socket.io doesn't give you an error, but if you change that to:
const socket = io("http://127.0.0.1:3000");
Then, it will work.
If you set DEBUG=socket.io-client in your environment, it won't show you an error, but it will show you that it's trying to connect to:
undefined//127.0.0.1:3000
which would give you a clue, I guess.
If you set DEBUG=* in your environment, you will get a lot more debug info (so much that it's a bit hard to sort through).
Set Logging and Debugging Socket.io for more info.

How to make socket.io accessible in all routes

I'm building a website that requires real-time communication and am using socket.io for that but am trying to make socket.io global. Have actually tried global.io (though it's not secure, just for testing purpose) but when I use this, I noticed I can't listen for event's using socket.emit maybe because it's a callback
const io = require('socket.io')(server);
io.on('connection', socket => {
console.log('connected')
})

socket.io client side in nodejs app

i am using socket.io for communication between server and client.
My client side is not a html. My client side is javascript file. so here is my code of client side
var io = require('socket.io-client')
var socket = io.connect('http://localhost:3000/home');
socket.on('connect', function () {
console.log(' Connected!');
});
On server side i have received the connection event but on client side connect event doesn't fire. I have tested through html way, it works but why its not working through a java script file.
I have no idea what you mean with tested through html way, but try socket.on("connection", ...),
not "connect".
could be related to the fact that you're specifying a namespace different from the default.
try to handle the connection at http://localhost:3000, instead of http://localhost:3000/home
var socket = io.connect('http://localhost:3000');
found a similar situation here

How to use the net module from Node.js with browserify?

I want to use the net module from Node.js on the client side (in the browser):
var net = require('net');
So I looked up how to get Node.js modules to the client, and browserify seems to be the answer. I tried it with jQuery and it worked like a charm.
But for some reason the net module does not want to work. If I write require('jquery') it works fine, but if I write require('net') it does not work, meaning my bundled .js file is empty.
I tried to search for something else, but the only thing I found is net-browserify on Github. With this, at least my bundle.js file is filled, but I get a JavaScript error using this (it has something to do with the connect function).
This is my code which works on the server side just fine:
var net = require('net-browserify');
//or var net = require('net');
var client = new net.Socket();
client.connect({port:25003}, function() {
console.log('Connected');
client.write('Hello, server! Love, Client.');
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
client.on('close', function() {
console.log('Connection closed');
});
I assume that net-browserify lets you use a specific connect function, but I don't know which.
How can I use the net module from Node.js on the client side?
This is because net gives you access to raw TCP sockets - which browsers simply cannot do from the JavaScript end. It is impossible for net to ever be ported to the client side until such an API is written (allowing arbitrary tcp traffic).
Your best bet if you want to send tcp data from the client to the server is using web sockets using the socket.io module or the ws one.
Your best bet if you want clients to communicate directly is to look into WebRTC

I'm receiving duplicate messages in my clustered node.js/socket.io/redis pub/sub application

I'm using Node.js, Socket.io with Redisstore, Cluster from the Socket.io guys, and Redis.
I've have a pub/sub application that works well on just one Node.js node. But, when it comes under heavy load is maxes out just one core of the server since Node.js isn't written for multi-core machines.
As you can see below, I'm now using the Cluster module from Learnboost, the same people who make Socket.io.
But, when I fire up 4 worker processes, each browser client that comes in and subscribes gets 4 copies of each message that is published in Redis. If there are are three worker processes, there are three copies.
I'm guessing I need to move the redis pub/sub functionality to the cluster.js file somehow.
Cluster.js
var cluster = require('./node_modules/cluster');
cluster('./app')
.set('workers', 4)
.use(cluster.logger('logs'))
.use(cluster.stats())
.use(cluster.pidfiles('pids'))
.use(cluster.cli())
.use(cluster.repl(8888))
.listen(8000);
App.js
redis = require('redis'),
sys = require('sys');
var rc = redis.createClient();
var path = require('path')
, connect = require('connect')
, app = connect.createServer(connect.static(path.join(__dirname, '../')));
// require the new redis store
var sio = require('socket.io')
, RedisStore = sio.RedisStore
, io = sio.listen(app);
io.set('store', new RedisStore);io.sockets.on('connection', function(socket) {
sys.log('ShowControl -- Socket connected: ' + socket.id);
socket.on('channel', function(ch) {
socket.join(ch)
sys.log('ShowControl -- ' + socket.id + ' joined channel: ' + ch);
});
socket.on('disconnect', function() {
console.log('ShowControll -- Socket disconnected: ' + socket.id);
});
});
rc.psubscribe('showcontrol_*');
rc.on('pmessage', function(pat, ch, msg) {
io.sockets.in(ch).emit('show_event', msg);
sys.log('ShowControl -- Publish sent to channel: ' + ch);
});
// cluster compatiblity
if (!module.parent) {
app.listen(process.argv[2] || 8081);
console.log('Listening on ', app.address());
} else {
module.exports = app;
}
client.html
<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script>
var socket = io.connect('localhost:8000');
socket.emit('channel', 'showcontrol_106');
socket.on('show_event', function (msg) {
console.log(msg);
$("body").append('<br/>' + msg);
});
</script>
I've been battling with cluster and socket.io. Every time I use cluster function (I use the built in Nodejs cluster though) I get alot of performance problems and issues with socket.io.
While trying to research this, I've been digging around the bug reports and similar on the socket.io git and anyone using clusters or external load balancers to their servers seems to have problems with socket.io.
It seems to produce the problem "client not handshaken client should reconnect" which you will see if you increase the verbose logging. This appear alot whenever socket.io runs in a cluster so I think it reverts back to this. I.E the client gets connected to randomized instance in the socket.io cluster every time it does a new connection (it does several http/socket/flash connections when authorizing and more all the time later when polling for new data).
For now I've reverted back to only using 1 socket.io process at a time, this might be a bug but could also be a shortcoming of how socket.io is built.
Added: My way of solving this in the future will be to assign a unique port to each socket.io instance inside the cluster and then cache port selection on client side.
Turns out this isn't a problem with Node.js/Socket.io, I was just going about it the completely wrong way.
Not only was I publishing into the Redis server from outside the Node/Socket stack, I was still directly subscribed to the Redis channel. On both ends of the pub/sub situation I was bypassing the "Socket.io cluster with Redis Store on the back end" goodness.
So, I created a little app (with Node.js/Socket.io/Express) that took messages from my Rails app and 'announced' them into a Socket.io room using the socket.io-announce module. Now, by using Socket.io routing magic, each node worker would only get and send messages to browsers connected to them directly. In other words, no more duplicate messages since both the pub and sub happened within the Node.js/Socket.io stack.
After I get my code cleaned up I'll put an example up on a github somewhere.

Resources