I have a very simple configuration in a node server with socket.io installed (a little bit more complex but essentially like this one):
var main = require('express')();
server = require('http').createServer(main);
io = require('socket.io')(server);
io.use(function(socket, next) {
console.log("middleware!");
next();
});
io.on('connection', function (socket) {
console.log('connected...');
socket.on('pong', function (data) {
console.log(data.message);
});
setTimeout(function() {
console.log("Saying hello");
socket.emit('ping', { message: 'Hello from server ' + Date.now() });
}, 1000);
});
server.listen(2080, function onCreateServerMain() {
console.log('Server main is listening on port 2080';
console.log('************************************************************');
});
In the client:
var socketIoScript,
loadSocketTimeout,
trialsToLoadSocketIo = 0,
APP_CFG = {baseUrl : "http://192.168.1.13:2080"};
function loadSocketIo(socketIoIp) {
socketIoScript = document.createElement('script');
socketIoScript.setAttribute('src', socketIoIp);
socketIoScript.setAttribute('onload', 'onSocketLoaded();');
document.head.appendChild(socketIoScript);
}
window.onSocketLoaded = function onSocketLoaded() {
if (typeof(io.connect) === 'function') {
var mSocket,
mIoSocket;
$timeout.cancel(loadSocketTimeout);
mIoSocket = new io.Manager(APP_CFG.baseUrl);
mIoSocket.connect(function(socket) {
console.log('Connected!!');
});
mIoSocket.on('error', function onSocketError(e) {
console.log('WebSocket Error ' + error);
});
mIoSocket.on('ping', function onPingReceived(e) {
console.log('Server emitted ping: ' + e.data);
mSocket.emit('pong', 'hi server!');
});
}
}
~(function onLoadSocketTimeout() {
var nextTimeout;
if (trialsToLoadSocketIo < 10) {
nextTimeout = 5000;
} else if (trialsToLoadSocketIo > 60) {
nextTimeout = 60000;
} else {
nextTimeout = 1000 * trialsToLoadSocketIo;
}
if (socketIoScript) {
document.head.removeChild(socketIoScript);
}
loadSocketIo(APP_CFG.baseUrl + '/socket.io/socket.io.js#' + trialsToLoadSocketIo);
loadSocketTimeout = $timeout(onLoadSocketTimeout, nextTimeout);
trialsToLoadSocketIo += 1;
})();
(I'm doing like this because it's mobile app so it may have not connection). I'm testing it with Brackets and Chrome. Server and client are in the same machine. In the app the script is loaded fine and it connects to the server as I can it see in node log (edit: and this is all what I get in the node console):
Server main is listening on port 2080
************************************************************
middleware!
connected...
Saying hello
Edit: in Chrome console I don't get any message, and any breakpoint stops at on listeners. If I stop node, the console for the Chrome immediately starts logging that it has been disconnected:
GET http://192.168.1.13:2080/socket.io/?EIO=3&transport=polling&t=1413066902601-6 net::ERR_CONNECTION_REFUSED
GET http://192.168.1.13:2080/socket.io/?EIO=3&transport=polling&t=1413066906606-7 net::ERR_CONNECTION_REFUSED
But I can't see any incoming message. In the app I don't receive any incoming message. Is there any reason why I could not communicate in this environment even if socket is successfully connected?
EDIT
No app is receiving events sent from the other side. Logs from node show this, logs from Chrome are empty.
EDIT
In Chrome app I don't receive console.log("Connected!");. But neither I receive ERR_CONNECTION_REFUSED errors: I don't receive anything.
EDIT
I managed to get console.log("Connected!"); in the app by changing Manager options:
mIoSocket = new io.Manager(APP_CFG.baseUrl, { autoConnect: false });
As it was auto connecting and the events were attached after connection was made, "Connected" was never reached. But I'm still not receiving any event in any app.
I had a similar issue were event callbacks on the server were not firing when emitting. My event names were ping and pong. As soon as I renamed these events everything worked.
I suspect the event names ping and pong are reserved by socket.io and so cannot be used.
Ok, so a few things :
First, var mSocket doesn't seem to be initialized, so it may be difficult for it to emit() anything (am I missing something?)
Second, when you do :
socket.on('pong', function (data) {
console.log(data.message);
});
the server expects to receive an object containing a message property, eg : data = {message:'hi server'} In your case, you send a string, so data is 'Hi server !' and your log will say 'undefined'. You should change this bit to :
socket.on('pong', function (data) {
console.log(data);
});
and you have a similar problem the other way around, you send an object : { message: 'Hello from server ' + Date.now() }, and are trying to log a data property which does not exist. Change this bit to :
console.log('Server emitted ping: ' + e.message);
And third , you have to listen for events on the socket, not the 'manager'
Client :
mIoSocket.connect(function(socket) {
console.log('Connected!!');
socket.emit('pong');
socket.on('error', function onSocketError(e) {
console.log('WebSocket Error ' + error);
});
socket.on('ping', function onPingReceived(e) {
console.log('Server emitted ping: ' + e.data);
socket.emit('pong', 'hi server!');
});
});
Server :
io.on('connection', function (socket) {
console.log('connected...');
socket.on('pong', function (data) {
console.log(data);
});
setTimeout(function() {
console.log("Saying hello");
socket.emit('ping', { message: 'Hello from server ' + Date.now() });
}, 1000);
});
Related
I am trying to host my parse server locally, but on my frontend I do not receive any events, not even the 'open' (connection opened) event. I also do not receive any errors that could help me solve the problem.
On my server I am using the following code:
var api = new ParseServer(
{
(... more properties and keys)
liveQuery:
{
classNames: ['Sticky', 'Canvas']
}
});
var app = express();
var mountPath = something;
app.use(mountPath, api);
var httpServer = require('http').createServer(app);
httpServer.listen(port, function(){ console.log('Running on http://localhost:' + port); });
var parseLiveQueryServer = ParseServer.createLiveQueryServer(httpServer);
On the frontend I am using the following code:
const stickyQuery = new Parse.Query(Sticky);
this.stickySubscription = await stickyQuery.subscribe();
console.log(this.stickySubscription); // This gets printed, nothing weird
this.stickySubscription.on('open', () => {
console.log('SUBSCRIPTION: opened'); // This is not printed
});
this.stickySubscription.on('create', (sticky) => {
console.log('SUBSCRIPTION: Sticky created, ', sticky); // This is also not printed
});
this.stickySubscription.on('update', (sticky) => {
console.log('SUBSCRIPTION: Sticky updated, ', sticky); // This is not printed
});
The subscription gets printed, and I don't see anything weird. It seems like connecting with the Parse server is going wrong. Does someone know what I'm missing or doing wrong?
Update: I added the following code to the frontend to show the websocket status and whether error events were triggered, but these events are also not triggered:
this.stickySubscription.on('close', () => {
console.log('SUBSCRIPTION: closed'); // This is not printed
});
Parse.LiveQuery.on('open', () => {
console.log('socket connection established'); // Gets printed
});
Parse.LiveQuery.on('close', () => {
console.log('socket connection closed'); // Is not printed
});
Parse.LiveQuery.on('error', (error) => {
console.log('socket error: ', error); // Is not printed
});
In your subscription query , write your className inside quotations:
const stickyQuery = new Parse.Query('Sticky');
Id like to auth eacht socket.io event on server side.
When i open angular page first, call method initSocket(login: Login), its ok.
Authentification successfull and i can send a message to server.
But if i restart server, angular reconnect to server by Htttp, but cant send a message by socketio.
In my server no messages in logs.
It seems that socketio-jwt block an clients message.
If i press F5 on client side its still ok again.
How to solve it without refreshing a page?
It seems taht i have to pass a token to each event on client side, after connection established to, but i dont know how to do it.
Angular 6:
public initSocket(login: Login): void {
this.socket = socketIo(SERVER_URL);
console.log('Socket init at' + SERVER_URL);
this.socket.emit('authenticate', { token: this.login.token });
this.socket.on('authenticated', function () {
console.log('socket is jwt authenticated');
});
this.socket.on('unauthorized', function (error, callback) {
if (error.data.type === 'UnauthorizedError' || error.data.code === 'invalid_token') {
// redirect user to login page perhaps or execute callback:
callback();
console.error('Users token has expired');
}
});
this.socket.on('disconnect', function (error) {
console.error('socket disconnect', error);
});
this.socket.on('connect_failed', function (error) {
console.error('socket connect_failed');
});
}
Server side:
io.sockets
.on('connection', socketioJwt.authorize({
secret: environment.secret,
timeout: 15000,
callback: false
})).on('authenticated', function (socket) {
clients[socket.decoded_token.id] = socket.decoded_token.login;
console.error('Connected: ', socket.decoded_token.login);
socket.on('message', async function (data) {
try {
// Проверка что пользователь пишите от себя
if (data.from === socket.decoded_token.id) {
data.totalCount = await db_helper.saveMessage(data);
if (clients[data.from] && clients[data.to]) {
io.sockets.connected[clients[data.to].socket].emit("message", data);
console.log("Sending from: " + clients[data.from].name + " to: " + clients[data.from].name + " '" + data.text + "'");
} else {
console.log('User does not exist: from=>', data.from, ':', clients[data.from], 'to=>', data.to, ':', clients[data.to]);
}
}
}
catch (error) {
console.error(error.message);
}
});
//Removing the socket on disconnect
socket.on('disconnect', function () {
});
});
This is because whenever your server/client goes offline, a new socket is created for re connection purpose and to establish a new connection i.e re connection, Server disconnects all it's previous connection from the same client, this process is asynchronous and thus is not visible to developers easily.
I would have also checked if my socket reconnection which is done is reconnected to the , by default socket reconnects to the port your client is connected to.
if that's the case then you need to reconnect with the help of io (socket manager)
There is also a possibility that your client re connection is set to false, you can check your socket properties by consoling it as follows:
this.socket.on('disconnect', function (error) {
console.log('disconnected', this)
//this sets whether the re connection is allowed or not
this.io._reconnection = true;
});
this.socket.on('reconnect', (error, callback) => {
console.log('reconnect succesfully', this);
//connect to the previously connected socket.
this.io.socket.reconnect()
});
i am trying to do a very simple real time notification with socket.io. for some reason i can't receive data or fire the event from server to client but from client to server yes. let me show my code:
Client Side
ngOnInit() {
this.socket.on('connect', function (res: any) {
console.log('Socket.io is connected on client side!'); // it shows on client console
});
this.socket.on('alarmsreceived', function (res: any) {
console.log(res + ' i am here now'); // is not firing
});
}
// this method fires from a click button
objectStatus = () => {
this.socket.emit('alarmsystem', 'i am client going to server');
}
Server
var io = require('socket.io').listen(server);
var connections = [];
io.of('/api/v1/monitoring').on('connect', function(socket){
connections.push(socket);
console.log('Connected %s sockets', connections.length); // i see connection on cmd
socket.on('disconnect', function() {
connections.splice(connections.indexOf(socket), 1);
console.log('Connected %s sockets', connections.length);
});
socket.on('alarmsystem', function(res) {
console.log(res); // this shows me the message from client
io.sockets.emit('alarmsreceived', 'I am server heading to client');
});
})
it seems pretty straight forward, but not firing the client event. Can someone help me what i am doing wrong here? Thanks in advance
I wondered if someone could help figure out what I am doing wrong:
My client web page initiates a connection with my server, and listens to a long running process whose state is getting updated in the db by a worker process on another thread, emitting updates back to the browser. I define a socket.io connection in the app.post() method. This is handled by the poll() function below (scroll down a bit past the invite checking code)
However, when a new web client connects, it's messages get added to the previous client's as if there were just one channel. Why isn't there a separate unique channel for each browser?
//Create server
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server);
io.set('log level', 1); // reduce logging
io.configure(function () {
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 10);
});
app.post('/api/users', function (req, res) {
if (!req.body.auth.accessToken) {
req.body.auth.accessToken = req.body.auth.authResponse.accessToken;
} //fb return object is different depending on whether it is a first login or subsequent
logger.log('debug', '/api/users:POST', req.body);
io.sockets.on('connection', function (socket) {
socket = socket;
socket.emit('update', {
status: 200 //send initialization ping
});
//check if user has valid invite, if not try to invite
db.getTotalUserInvites(function (err_inv, res_total) {
db.getUserInvite(req.body.fid, function (err_check, res_check) {
logger.log('debug', 'Total invites issued=' + res_total);
//process report - all we need is accesToken, processReport will do the rest
mine_fb.processUser(req.body.auth.accessToken, socket, function (User,socket) { //pass channel properly
db.getReportStatus(User.fid,socket, function (result,socket) {
logger.log('debug', 'report status', result);
if (result) {
if (socket && (result.report_status == -1)) {
logger.log('debug', 'report already processed. retrieving uniq_id ' + result.uniq_id);
socket.emit('update', {
status: -1,
uniq_id: result.uniq_id
});
return true;
} else {
if (socket && (result.report_status >= 0)) {
logger.log('debug', 'we are in the middle of processing report ' + result.uniq_id);
//in this case we become a listener and not a speaker
function poll(socket) {
db.getReportStatus(User.fid, socket,function (r,socket) {
socket.emit('update', { //!!!! THIS EMITS TO ALL CONNECTED BROWSERS
status: r.report_status,
uniq_id: r.uniq_id
}); //...socket
if ((r.report_status >= 0) && (socket)) {
logger.log('debug', 'polling...');
_.delay(poll, 2000, socket);
}
}); //get rerpot
}; //end poll
socket.on('disconnect', function () {
socket=null;
});
poll(socket);
} // else we're in the middle
} //done checking status
} //end of seq
});
return res.send();
});
});
});
});
});
While it is not clear how to help you I can tell what's going on in your code:
app.post('/api/users', function (req, res) {
// some code
io.sockets.on('connection', function (socket) {
// some code
});
});
Whenever a user POSTs something to /api/users a new handler is attached to io.sockets (that's what .on does). But these handlers are never removed, so each time a new connection is established all attached handlers fire. That's where your broadcasting comes from.
You have to separate app.post(...) from io.sockets.on('connection',...) (they should be independent, both defined at module level, not nested). I'm sure it won't be easy (you will probably have to authenticate a user twice for example) but that's the only reasonable way.
You shouldn't put your io.sockets.on('connection', function (socket) inside the app.post scope.
Just put it outside and try again, it will probably work correctly.
Listening to connexion should be done once when the server starts, not each time a client hits some URL.
I'm trying out node.js and socket.io. I wan't to use to remove a ping function I have to get updates from my server. Here is an example code of what I'm doing:
var app = require('http').createServer(),
io = require('socket.io').listen(app),
cp = require('child_process');
app.listen(8080);
//I check a global value for all the connected users from the php command line
var t = setInterval(function(){
cp.exec('/usr/bin/php /Users/crear/Projects/MandaFree/symfony api:getRemainingMessages',
function(err, stdout){
if (err) {
io.sockets.emit('error', 'An error ocurred while running child process.');
} else {
io.sockets.emit('change', stdout);
}
console.log('Remaining messages: ' + stdout);
});
}, 3000);
var remaining = io.of('/getRemainingMessages')
.on('connection', function(socket){
socket.on('disconnect', function(){});
});
The Issue here, is that when I call io.sockets.emit() the debug console tells me it is doing something, but it looks like it is not getting to the clients. Because they are doing nothing.
I use to have one interval for every connected client, and when I used socket.emit() it did worked. But it is not the optimal solution.
UPDATE:
Here is my client side code.
var remaining = io.connect('http://127.0.0.1:8080/getRemainingMessages');
remaining.on('change', function(data){
console.log('Remaining messages: ' + data );
$('#count').html(data);
});
remaining.on('error', function(error){
console.log(error);
});
Had a very similar issue couple of days back and looks like socket.io had some changes in the API. I have never worked with symfony and am hoping the issues are the same.
I have a working demo of socket.io sending and receiving a message - uploaded to https://github.com/parj/node-websocket-demo as a reference
Essentially two changes
On Server side - changed socket.on to socket.sockets.on
var socket = io.listen(server);
socket.sockets.on('connection', function(client)
On Client side - URL and port not required as it is autodetected.
var socket = io.connect();
This has been tested using Express 2.5.2 and Socket.io 0.8.7
I have amalgamated your server code with mine, would you be able to try this on the server and my client javascript and client html just to see if it is working?
var socket = io.listen(server);
socket.sockets.on('connection', function(client){
var connected = true;
client.on('message', function(m){
sys.log('Message received: '+m);
});
client.on('disconnect', function(){
connected = false;
});
var t = setInterval(function(){
if (!connected) {
return;
}
cp.exec('/usr/bin/php /Users/crear/Projects/MandaFree/symfony api:getRemainingMessages',
function(err, stdout){
if (err) {
client.send('error : An error ocurred while running child process.');
} else {
client.send('change : ' + stdout);
}
console.log('Remaining messages: ' + stdout);
});
}, 3000);
t();
});