socket.io Websocket connection inside a HTML5 SharedWorker - websocket

I hope you all are doing well. I'm trying to establish connection to socket.io server from inside of the worker.js file using importScripts which loads the socket.io-client js file which is in the same directory with worker.js. After loading socket.io-client
by using var socket = io.connect('http://38.98.xxx.xxx:6000'); I am trying to establish connection to socket.io server on different host, but it ain't working. Please point me in the right direction.I appreciate any help.
<script>
var worker = new SharedWorker("http://baseUrl.com/js/push/worker/worker.js");
worker.port.addEventListener("message", function(e) {
console.log("Got message: " + e.data);
}, false);
worker.port.start();
worker.port.postMessage("start");
</script>
worker.js
importScripts('socket.io.js');
var socket = io.connect('http://38.98.154.167:6000');
var connections = 0;
self.addEventListener("connect", function(e) {
var port = e.ports[0];
connections ++;
port.addEventListener("message", function(e) {
if (e.data === "start") {
port.postMessage('hello');
}
}, false);
port.start();
}, false);
socket.on('connect', function () {
port.postMessage('connect');
});
socket.on('disconnect', function () {
port.postMessage('disconnect');
});

I figured it out. Just had to move
socket.on('connect', function () {
port.postMessage('connect');
});
socket.on('disconnect', function () {
port.postMessage('disconnect');
});
into the self.addEventListener("connect", function(e) {});in the worker.js and change from var socket=io.connect('http://38.98.xxx.xxx:6000');
to
var socket = io('http://38.98.xxx.xxx:6000');
Here is the working example is case if anybody needs.
worker.js
importScripts('socket.io.js');
var socket = io('http://38.98.xxx.xxx:6000');
var connections = 0;
self.addEventListener("connect", function(e) {
var port = e.ports[0];
connections ++;
port.addEventListener("message", function(e) {
if (e.data === "start") {
port.postMessage('hello');
}
}, false);
port.start();
socket.on('push', function(pushed){
port.postMessage(pushed);
});
socket.on('connect', function () {
port.postMessage('connect');
});
socket.on('disconnect', function () {
port.postMessage('disconnect');
});
}, false);

There is a drop in replacement for const io = require('socket.io-client');
which runs the connection for the returned socket in a dedicated webworker. It is
const io = require('sockerworker.io');
const socket = io([url][, options]);
Instead of writing your own boilerplate for the webworker, you could use this. It is available here via npm. (disclosure: I am its author.)

Related

socket io unique channel - emit without specifying the room

On my project each user is joining his unique channel (I know that the user is also in a socked id channel).
Client
var socket = io('http://localhost:8000/');
var room = "unique_id";
socket.on('connect', function () {
socket.emit('room', room);
});
socket.on("unique_id", function() {
console.log("test");
})
On the server side I am checking the rooms a user is connected to:
var io = require('socket.io')(8000);
io.on('connection', function(socket) {
var room;
socket.on('room', function(unique_id) {
socket.join(unique_id);
room = unique_id;
console.log(io.sockets.adapter.rooms); //show the unique_id room
io.to(room).emit('hello', 'msg');
});
socket.on(room, function(data) {
console.log(room);
})
});
Output on connect
{ 'DQOt2DX2IsHh-m9nAAAC': { sockets: { 'DQOt2DX2IsHh-m9nAAAC': true }, length: 1 },
'unique_id': { sockets: { 'DQOt2DX2IsHh-m9nAAAC': true }, length: 1 } }
Now I am using elephant.io to emit to the client as follows
$client = new Client(new Version1X('http://localhost:8000'));
$client->initialize();
$client->emit('unique_id', ['news' => 'bar']);
$client->close();
I think there is something wrong on my server side but I am not able to solve it. I need to process the events for the unique_id but how?
server side
var io = require('socket.io')(8000);
io.on('connection', function(socket) {
var room;
socket.on('room', function(address) {
socket.join(address);
room = address;
console.log(io.sockets.adapter.rooms);
io.to(room).emit('hello', 'msg');
});
socket.on('message', function(data) {
console.log(data.unique_id);
io.to(data.unique_id).emit('hello', 'msg');
})
});
elephant.io
$client->emit('message', ['unique_id' => 'foo']);
This is my solution which is working for me.

Reconnect stomp when disconnected

I am using the following code to create/subscribe to a topic and handle the messages. Sometimes the connection gets lost and the error says:
Whoops! The connection was lost...
I would like to know if there is a way to reconnect it. Is it possible in the error callback or define the whole code in a method and call it recursively in error callback ?
$(document).ready(function () {
........
...............
try {
var socket = new SockJS("${createLink(uri: '/stomp')}");
var client = Stomp.over(socket);
client.connect({}, function () {
client.subscribe("/topic/${userInstance?.username}",
function (message) {
............
....................
});
});
} catch (error) {
console.log("ERROR: " + error.toString());
}
});
I managed to do it using failure callback and connect again. It will keep trying as long as it will fail.
This is what I am using in a Polymer element:
ready: function() {
this.connectWs();
},
connectWs: function() {
this.socket = new WebSocket(this.socketUrl);
this.stompClient = Stomp.over(this.socket);
this.stompClient.debug = null;
this.stompClient.connect({},
function(frame) {
// Connection OK
}.bind(this),
function(e) {
console.error(e, "Reconnecting WS", this.socketUrl);
window.setTimeout(function() {
this.connectWs();
}.bind(this), 2500);
}.bind(this)
);
},

Difference between io.on and socket.on in Socket.io?

I am confused on what the 'socket' parameter is that is passed with the function (In 'The enigma' section). Then the parameter gets used 'socket.on'. What is the difference between io.on and socket.on?
The following code is slightly adapted from the Socket.io chat application example.
Variables
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app)
var io = require('socket.io').listen(server);
The enigma
io.on('connection', function (socket) {
console.log('user connected');
socket.on('message', function(msg) {
console.log('message: ' + msg);
io.emit('message', msg);
})
});
Start server
server.listen(3000, function() {
console.log('server is running');
});
index.jade
body
script(src="/socket.io/socket.io.js")
form(method='post', action="/")
input(type='text', id='user', autocomplete='off')
input(type='submit', onClick="myFunc()")
strong messages:
p(id="messages")
script.
var socket = io();
socket.on('message', function(msg) {
console.log('client: ' + msg);
});
function myFunc() {
var text = document.getElementById('user');
socket.emit('message', text.value);
text.value = '';
};
In your code example, io is a Socket.IO server instance attached to an instance of http.Server listening for incoming events.
The socket argument of the connection event listener callback function is an object that represents an incoming socket connection from a client.
Both of them can listen for events with the on method.
It might help you visually understand how the two are separate if you re-imagine your code sample like this:
var connectionEvent = function(socket) {
console.log('user connected');
socket.on('message', function(msg) {
console.log('message: ' + msg);
io.emit('message', msg);
});
};
io.on('connection', connectionEvent);

Load chat messages upon page load using websockets on node.js

Hi I'm developing a chat application using nodejs I'm new to node so I'm not very well familiar on its capabilities... I have made my application store its chat messages on mysql database only but I need to also display the past message and current one of a user here is the index.js
var mysql = require('mysql');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var validator;
var connection = mysql.createConnection({ // setup the connection
host : "localhost",
user : "root",
password: "",
})
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
//res.sendfile(__dirname + '/' +validator);
res.send(validator);
});
//you should have only one io.on('connection')
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
var myMsg= msg; // obtain the incoming msg
var strQuery = "INSERT INTO chat_storage(chat) VALUES(?)"; // your SQL string
connection.query("use schat"); // select the db
connection.query( strQuery, myMsg, function(err, rows){
if(err) {
// handle errors
} else {
io.emit('chat message', msg);
// message received
}
});
});
});
getStdout('php', ['message.php'], function(output) {
validator = output;
//start your server after you get an output
http.listen(3000, function(){
console.log(validator);
});
});
now here is the page for loading the chat messages
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(document).ready(function(){
$.ajax({
url: "localhost:3000/includes/message/store_chat.php",
type: "POST",
dataType: "html",
success: function (result) {
$("#messages").html(result);
}
});
});
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>
My idea was to the chat messages once the page loads I was trying to achieve it using ajax as you can see on the script that I have provided.. but it was no good didnt work at all Please help me
Couple of suggestions:
1) Store all of your messages in-memory ( unless you see this growing to several MB of data ) so that you can catch up any new client quickly.
2) Use socket.io to send the chat messages that have been stored rather than an AJAX call.
I've also included SequelizeJS instead of raw MySQL - It has a much cleaner raw query model and allows you to transition into a DAO model of sorts if you want to.
app.js
// Highly suggest replacing raw mysql with SequelizeJS - http://sequelizejs.com/
var Sequelize = require('sequelize'),
app = require('express')(),
http = require('http').Server(app),
io = require('socket.io')(http);
var validator;
var messages = [];
var sequelize = new Sequelize('schat', 'root', '');
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
res.send(validator);
});
io.on('connection', function(socket){
// Send all previously sent messages
for( i in messages ) {
socket.emit('chat message', messages[i]);
}
socket.on('chat message', function(msg){
console.log('message: ' + msg);
// Push the message into the in-memory array.
messages.push(msg);
// Storage the message for when the application is restarted.
sequelize.query('INSERT INTO chat_storage(chat) VALUES("'+msg'")').success(function() {
// Insert was successful.
}).error(function (err) {
// Error inserting message
});
// Send the message to everyone
socket.broadcast.emit('chat message', msg);
});
});
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
// Load Messages
sequelize.query('SELECT chat FROM chat_storage').success(function (rows) {
for( i in rows ) {
messages.push(rows[i].chat);
}
getStdout('php', ['message.php'], function(output) {
validator = output;
http.listen(3000, function(){
// Start server.
});
});
}).error(function (err) {
// Error!
});
php include
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#messages').append($('li').text($('#m').val()));
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>

Signalr 2.0.0 doesn't behave as previous version

I have updated my server solution to work with MVC 5 and latest version of signalr and have two major issues:
I have overriden the OnConnected function and it is not being invoked.
Messages to client are not being received , calls from the client are being received
this is the client code
define(['jquery', 'toastr', 'Q'], function($, toastr, Q) {
var incidentHubProxy;
var deferred = Q.defer();
var connect = function() {
var connection = $.hubConnection(localStorage.url);
$.connection.hub.logging = true;
incidentHubProxy = connection.createHubProxy('notification');
connection.start()
.done(function () {
toastr.success('Now connected, connection ID=' + connection.id);
setInterval(function () {
incidentHubProxy.invoke('ping');
}, 3000);
deferred.resolve();
})
.fail(function () { toastr.error('Could not connect'); });
incidentHubProxy.on('notify', function (data) {
toastr.info(data.topic);
toastr.info(data.data);
});
incidentHubProxy.on('pong', function (data) {
toastr.info('got pong');
});
return deferred.promise;
};
var joinGroup = function (groupName) {
incidentHubProxy.invoke('joinGroup', groupName);
};
return {
connect: connect,
joinGroup: joinGroup
};
});
i have updated the code to that and still dont work
define(['jquery', 'toastr', 'Q'], function($, toastr, Q) {
var incidentHubProxy;
var deferred = Q.defer();
var connect = function() {
var connection = $.hubConnection(localStorage.url);
$.connection.hub.logging = true;
incidentHubProxy = connection.createHubProxy('notification');
incidentHubProxy.notify = function(data) {
toastr.info(data.topic);
toastr.info(data.data);
};
incidentHubProxy.pong = function(data) {
toastr.info('got pong');
};
connection.start()
.done(function () {
toastr.success('Now connected, connection ID=' + connection.id);
setInterval(function () {
incidentHubProxy.invoke('ping');
}, 3000);
deferred.resolve();
})
.fail(function () { toastr.error('Could not connect'); });
return deferred.promise;
};
var joinGroup = function (groupName) {
incidentHubProxy.invoke('joinGroup', groupName);
};
return {
connect: connect,
joinGroup: joinGroup
};
});

Resources