Angular 6 authentificate client after server restart socket.io socketio-jwt - node.js

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()
});

Related

Socket.io communicating from server to client not happening

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

Client is trying to get data with Socket.io but doesn't seem to connect

I have set up sockets on my client and server, but I can't seem to get my data to come into my client. It seems they are connecting properly, I just can't get any data to come through. There are no error messages either.
Here is my server code:
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('custom-message', function () {
console.log("Hitting messages socket");
Message.find(function(err, messages){
if(err){
socket.emit('custom-message', err)
} else {
socket.emit('custom-message', messages);
}
})
});
});
Here is the function in the client that connects to the socket:
loadMessagesFromServer: function(){
console.log("About to load messages")
socket.on('custom-message', function(msg){
console.log("connected in client", msg)
});
},
Like I said it is a pretty simple example, I just can't seem to get the data in loadMessagesFromServer .. And there are no erros, the only way I have been debugging is trying different things..
You are listening on the event messages. So you need to emit the same event not socket.emit('messages: err', err). Try with socket.emit("messages", error). Moreover, in your server-side code, you need first to receive a message event and only then your socket will emit the messages. Remove the socket.on(custom-messages). Why do you need it?
Server-side code
io.on('connection', function (socket) {
/* Here a client connection is established. The on("connection")
* event will be triggered as many times as`io.connect("the-uri")`
* is triggered (and succeeded) in the client`
*/
// Listening for the post event
socket.on("post", function(messages){
console.log("client posted data:", messages)
// Find messages and emit result
Message.find(function(err, messages){
if(err){
socket.emit('error', err)
} else {
socket.emit("message", messages);
}
});
});
});
Client-side code
registerOnMessageFromServerListener: function(){
socket.on("message", function(msg){
console.log("received message:", msg);
});
registerOnErrorFromServerListener: function(){
socket.on("error", function(error){
console.log("an error occured:", error);
});
registerOnMessageFromServerListener();
registerOnErrorFromServerListener();
socket.emit("post", "a-message");
Also make sure that you call the loadMessagesFromServer before you establish the socket connection

Sails and Socket publishUpdate Can't Send data

I try learn Socket With sails but I have a problem with publishUpdate can't send data.
Let me show my code
User Module server Side
'subscribe': function(req,res,next){
User.find(function(err,users){
if (err) return next(err);
User.watch(req.socket);
User.subscribe(req.socket, users);
console.log('now user is subscribe in ',req.socket.id);
res.send(200);
});
}
app.js Client Side
(function(io){
// Connect To Socket
var socket = io.sails.connect();
if(typeof console !== 'undefined'){
console.log('Connecting to Sails.js ...');
}
socket.on('connect', function(){
// is undefined
console.log("This is handshake: ",socket.handshake)
// is undefined
console.log("This is from the connect: ", socket.id);
//console.log(socket);
// listen for message
socket.on('message', function(message){
console.log('New Message is Coming', message);
});
// Subscribe to the user model classroom and instance room
io.socket.get('/user/subscribe',function(){
//console.log('user now is subscribe ');
});
// log
console.log(
'Socket is now connected and globally accessible as `socket`.\n' +
'e.g. to send a GET request to Sails, try \n' +
'`socket.get("/", function (response) ' +
'{ console.log(response); })`'
);
});
})(
// In case you're wrapping socket.io to prevent pollution of the global namespace,
// you can replace `window.io` with your own `io` here:
window.io
);
in Session module server Side
user.online = true;
user.save(function(err,user){
//req.isSocket
var io = sails.io;
// emit to all sockets (aka publish)
// including yourself
I try this and work great and I revived message
//io.sockets.emit('message', {thisIs: 'USer Log in Id is ' + user.id});
User.publishUpdate(user.id,{
loggedIn : true,
id : user.id
});
console.log('User is signin', user.id);
// User Redirect To His Profile
if (user.admin){
res.redirect('/user/');
return;
}
res.redirect('/user/show/'+ user.id);
});
Now I try reload the server and show me in chrome browser
This is handshake: undefined
app.js:14 This is from the connect: undefined
app.js:32 Socket is now connected and globally accessible as socket.
e.g. to send a GET request to Sails, try
socket.get("/", function (response) { console.log(response); })
I remove publishUpdate and try emit.
I try this and work great and I revived message.
//io.sockets.emit('message', {thisIs: 'USer Log in Id is ' + user.id});

Socket.io connected but not communicating

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);
});

Node.js: client doesn't die when TCP connection closes

I built a simple TCP server and a simple TCP client in Node.js
Now, when the client sends "exit" to the server, the connection is successfully closed. The server deletes the socket from its sockets list and sends "Bye bye!" to the client.
The connection on the client is closed as well but the app is still waiting for other inputs, so it doesn't die and I'm forced to type CTRL+C.
I tried adding process.exit() after connection closes but it doesn't work:
CLIENT CODE:
var net = require('net'),
config = require(__dirname + '/config.json'),
connection = net.createConnection(config.port, config.host);
connection.setEncoding('utf8');
connection.on('connect', function () {
console.log('Connected');
});
connection.on('error', function (err) {
console.error(err);
});
connection.on('data', function (data) {
console.log('» ' + data);
});
connection.on('close', function() {
console.log('Connection closed');
});
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.end();
process.exit();
}
else {
connection.write(data);
}
});
process.stdin.resume();
SERVER CODE:
var server = require('net').createServer(),
config = require(__dirname + '/config.json'),
sockets = [];
server.on('connection', function (socket) {
socket.setEncoding('UTF-8');
socket.on('data', function (data) {
console.log('Received data: ' + data);
if (data.trim().toLowerCase() === 'exit') {
socket.write("Bye bye!\n");
socket.end();
}
else {
sockets.forEach(function (client) {
if (client && client != socket) {
client.write(data);
}
});
}
});
socket.on('close', function () {
console.log('Connection closed');
sockets.splice(sockets.indexOf(socket), 1);
console.info('Sockets connected: ' + sockets.length);
});
sockets.push(socket);
});
server.on('listening', function () {
console.log('Server listening');
});
server.on('close', function () {
console.log('Server is now closed');
});
server.on('error', function (err) {
console.log('error:', err);
});
server.listen(config.port);
EDIT:
I added a client connection "on close" event handler. So, the string "Connection closed" is now printed by the server and by the client too.
I think you're looking for this: socket.unref().
From Node.js documentation (https://nodejs.org/api/net.html#net_socket_unref):
socket.unref()#
Calling unref on a socket will allow the program to exit if this is the only active socket in the event system. If the socket is already unrefd calling unref again will have no effect.
Some time ago when improving the tests suite for node-cubrid module, I had encountered the same problem. After all tests have passed, nodeunit process didn't quit because node-cubrid was using connection.end() to close the client socket when timeout occurs, just like you did.
Then I replaced connection.end() with connection.destroy(), a cleaner way to ensure the socket is really closed without actually terminating the running process, which, I think, is a better solution than the above suggested process.exit(). So, in your client code context, I would do:
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.destroy();
}
else {
connection.write(data);
}
});
According to Node.js documentation:
socket.destroy()
Ensures that no more I/O activity happens on this socket. Only necessary in case of errors (parse error or so).
I doubt that if ((new String(data)).toLowerCase() === 'exit') is succeeding because data most likely has a trailing newline (in your server, you trim() before doing the comparison, but not in the client).
If that's fixed, you've got a logic problem: when getting "exit" you close the connection without sending "exit" to the server, so the server code that looks for "exit" will never execute.
You have to put the process.exit() instruction only on the last event handler. So, in this case you have to put it inside the client connection "on close" event handler:
CLIENT:
connection.on('close', function() {
console.log('Connection closed');
process.exit();
});
Try with Event: 'close' in the server:
http://nodejs.org/api/net.html#net_event_close

Resources