I'm testing out Socket.IO for a new project that uses Compound.js (built on node.js/Express.js), but I've come across a problem. I've managed to get the basics working and the following message works fine:
Server-side JS (applicationname/config/initializers/socketio.js):
var sio = require('socket.io');
var http = require('http');
var activeClients = 0;
module.exports = function (compound) {
var app = compound.app;
var server = http.createServer(app);
compound.server = server;
var io = compound.io = sio.listen(server);
io.sockets.on('connection', function (socket) {
activeClients +=1;
var connections = setInterval(function () {
socket.emit('news', { clients: activeClients });
}, 1000);
socket.on('disconnect', function () {
activeClients -= 1;
io.sockets.emit('user disconnected');
clearInterval(connections);
});
});
}
Front-end JS (applicationname/public/index.html):
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
function msgReceived(msg){
$clientCounter.html(msg.posts);
}
$(document).ready(function () {
$clientCounter = $("#client_count");
socket.on('news', function (data) {
msgReceived(data);
socket.emit('my other event', { my: 'data' });
});
});
</script>
What I'm trying to do now is get the number of posts that have been made on the server. I used a default scaffold to generate the Posts method, controller and views.
How do I now find the total number of posts and pass that value to the server-side JS?
Simply count the number of emits on the server side and send that?
...
var emits = 0;
var connections = setInterval(function () {
emits++;
socket.emit('news', { clients: activeClients , num_messages: emits});
}, 1000);
...
Or create a specific message that can be polled from the client
Related
In the postgresql database i have an "alarm" table, a peculiar alarm panel.
I need to display the appearance of new events in real time. Using the socket.io library,
I was able to display notifications of new events, but I needed that the whole database was unloaded at startup,
and in my cases this does not happen, I ask you how to implement it better, thanks in advance.
app.js
var io = require('socket.io').listen(9999);
var pg = require ('pg');
var con_string = 'postgres://username:password#localhost/dbname';
var pg_client = new pg.Client(con_string);
pg_client.connect();
var query = pg_client.query('LISTEN alarmevent');
io.sockets.on('connection', function (socket) {
socket.emit('connected', { connected: true });
socket.on('ready for data', function (data) {
pg_client.on('notification', function(title) {
socket.emit('update', { message: title });
console.log(title);
});
});
});
index.html
WEB_SOCKET_SWF_LOCATION = 'inc/WebSocketMain.swf';
var socket = io.connect('http://localhost:9999');
socket.on('connected', function (data) {
socket.emit('ready for data', {});
});
socket.on('update', function (data) {
$('#future').append(data.message.payload + "<br/>");
});
I've written my application and now I've activated New Relic and it pings my app every 30 mins to keep my server alive (heroku). Otherwise before the server would just idling and then taking a lot of time to restart on the first request.
I'm running a socket.io server and the problem that i'm facing now, is that after a lot of time that the server runs, it gets stuck in answering to the namespaces. The application doesn't give any fatal error, it keeps running but just stops answering.
It keeps working as usual (still detects and log new connected clients), but just doesn't sends the messages.
Nothing weird on the logs.
Could you help to check if I'm doing anything really wrong with my code that I shouldn't do and might create problems? (e.g. too many listeners etc.)
I've made a little summary of my code, so there might be some little stupid syntax errors, but the flow should be this one. Everything is repeated by 4, because I have 4 namespaces and 4 different queries.
var app = require('express')();
var http = require('http').Server(app);
var cors = require('cors');
var io = require('socket.io')(http);
var PORT = process.env.PORT || 8080;
var sensorSocket = io.of('/namespace1'); //This gives back all the sensor at once with just now values.
var oldata = [];
var intervalRefresh=300;
app.use(cors());
var mysql = require('mysql');
var connectionsArray = [];
var connection = mysql.createConnection({
host: 'xxx',
user: 'xxx',
password: 'xxx',
database: 'xxx',
port: xx,
dateStrings: 'date'
})
//websockets creation/connection
app.get('/', function (req, res) {
res.sendFile(__dirname + '/client.html');
});
http.listen(PORT, function () {
console.log('\n\n\n\n listening on port: %s', PORT);
});
io.of('/namespace1').on('connection', function (socket) {
newconnectionSensors = 1;
console.log("Client id: %s connected on /sensors", socket.id);
console.log(io.of('/sensors').sockets.length);
socket.on('disconnect', function () {
console.log("Just left the ship grrarr : %s", socket.id);
});
});
io.of('/namespace2').on('connection', function (socket) {
[..Similar to the previous one..]
});
io.of('/namespace3').on('connection', function (socket) {
[..Similar to the previous one..]
});
io.of('/namespace4').on('connection', function (socket) {
[..Similar to the previous one..]
});
//Above here I do the same request every 300ms to the db and if there is any change, sends it into the client.
var CheckDB = setInterval(function (sensorSocket) {
if (io.of('/namespace1').sockets.length > 0) {
var query = connection.query('Query...'),
data = []; // this array will contain the result of our db query
query
.on('error', function (err) {
// Handle error, and 'end' event will be emitted after this as well
console.log(err);
})
.on('result', function (result) {
data.push(result);
})
.on('end', function () {
if ((JSON.stringify(oldata) != JSON.stringify(data)) || newconnection == 1) { //if new data is different than the old data, update the clients
io.of('/namespace1').emit('message', dataSensors, io.of('/namespace1').sockets.id);
newconnection = 0;
oldata = data.slice(0); //copy of data to oldata
}
});
}
}, intervalRefresh);
var CheckDB2 = setInterval(function (sensorSocket) {
[..Similar to the previous one..]
}, intervalRefresh);
var CheckDB3 = setInterval(function (sensorSocket) {
[..Similar to the previous one..]
}, intervalRefresh);
var CheckDB4 = setInterval(function (sensorSocket) {
[..Similar to the previous one..]
}, intervalRefresh);
Found the error.
The real mistake was that I was not having really clear the Non-Blocking concept of NodeJS, so in the code I was not waiting for the answers from the MySQL server and instead I was just throwing queries to the server so the results were going to arrive after hours.
I've fixed by making an escamotage. Basically I added a var (queryexecuting) which is checking if the query has been finish to execute or not.
var CheckDB = setInterval(function (sensorSocket) {
if (io.of('/namespace1').sockets.length > 0 && queryexecuting==0) { //If there are connected clients and there is no query executing.
queryexecuting=1; //Means the query is working
var query = connection.query('Query...'),
data = [];
query
.on('error', function (err) {
console.log(err);
})
.on('result', function (result) {
data.push(result);
})
.on('end', function () {
if ((JSON.stringify(oldata) != JSON.stringify(data)) || newconnection == 1) {
io.of('/namespace1').emit('message', dataSensors, io.of('/namespace1').sockets.id);
newconnection = 0;
oldata = data.slice(0);
}
queryexecuting=0; //Means the query has been finished
});
}
}, intervalRefresh);
I want to update an array on the server and broadcast it to all clients. The problem I am facing is that I need the client parameter to broadcast. On the server:
var socket = io.listen(8000);
var plateaus = [];
setInterval(function () {
plateaus.push('new data');
-- send the updated array to all clients --
}, 1000);
socket.sockets.on("connection", setEventListeners);
function setEventListeners(client)
// loadExistingPlayer(client); <- normally I use the client param
}
How do I broadcast the updated array? Many thanks!
answer on my own question (hope I will help anyone in the future).
You can store the client parameter in an array and access it anytime:
var socket = io.listen(8000);
var plateaus = [];
var clients = []
setInterval(function () {
plateaus.push('new data');
for(var i = 0; i < clients.length; i++){
clients[i].emit('updata all clients', plateaus)
}
}, 1000);
socket.sockets.on("connection", setEventListeners);
function setEventListeners(client)
console.log('new client');
clients.push(client);
}
After you connect your client, wouldn't you just emit an event from your server and your client could listen to that event with on(event, cb)?
From the Docs: http://socket.io/docs/
Server:
var io = require('socket.io')(server);
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Client:
var socket = io('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
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 get session id of client in my socket.io client.
here is my socket.io client :
var socket = new io.Socket(config.host, {port: config.port, rememberTransport: false});
// when connected, clear out display
socket.on('connect',function() {
console.log('dummy user connected');
});
socket.on('disconnect',function() {
console.log('disconnected');
});
socket.connect();
return socket;
I want to get session id of this client , how can i get that ?
Have a look at my primer on exactly this topic.
UPDATE:
var sio = require('socket.io'),
app = require('express').createServer();
app.listen(8080);
sio = sio.listen(app);
sio.on('connection', function (client) {
console.log('client connected');
// send the clients id to the client itself.
client.send(client.id);
client.on('disconnect', function () {
console.log('client disconnected');
});
});
On socket.io >=1.0, after the connect event has triggered:
var socket = io('localhost');
var id = socket.io.engine.id
I just had the same problem/question and solved it like this (only client code):
var io = io.connect('localhost');
io.on('connect', function () {
console.log(this.socket.sessionid);
});
* Please Note: as of v0.9 the set and get API has been deprecated *
The following code should only be used for version socket.io < 0.9
See: http://socket.io/docs/migrating-from-0-9/
It can be done through the handshake/authorization mechanism.
var cookie = require('cookie');
io.set('authorization', function (data, accept) {
// check if there's a cookie header
if (data.headers.cookie) {
// if there is, parse the cookie
data.cookie = cookie.parse(data.headers.cookie);
// note that you will need to use the same key to grad the
// session id, as you specified in the Express setup.
data.sessionID = data.cookie['express.sid'];
} else {
// if there isn't, turn down the connection with a message
// and leave the function.
return accept('No cookie transmitted.', false);
}
// accept the incoming connection
accept(null, true);
});
All the attributes, that are assigned to the data object are now accessible through the handshake attribute of the socket.io connection object.
io.sockets.on('connection', function (socket) {
console.log('sessionID ' + socket.handshake.sessionID);
});
On Server side
io.on('connection', socket => {
console.log(socket.id)
})
On Client side
import io from 'socket.io-client';
socket = io.connect('http://localhost:5000');
socket.on('connect', () => {
console.log(socket.id, socket.io.engine.id, socket.json.id)
})
If socket.id, doesn't work, make sure you call it in on('connect') or after the connection.
For some reason
socket.on('connect', function() {
console.log(socket.io.engine.id);
});
did not work for me. However
socket.on('connect', function() {
console.log(io().id);
});
did work for me. Hopefully this is helpful for people who also had issues with getting the id. I use Socket IO >= 1.0, by the way.
Try from your code
socket.socket.sessionid
ie.
var socket = io.connect('http://localhost');
alert(socket.socket.sessionid);
var sendBtn= document.getElementById('btnSend');
sendBtn.onclick= function(){
var userId=document.getElementById('txt1').value;
var userMsg = document.getElementById('txt2').value;
socket.emit('sendto',{username: userId, message: userMsg});
};
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
socket.on('message',function(data){ console.log(data);});
Try this way.
var socket = io.connect('http://...');
console.log(socket.Socket.sessionid);