Close the socket.io connection when user changes route in Angular 8 - javascript

Socket.io closes the connection when user try to close the tab or window but it does not when user navigate to other route in same angular app, the disconnect event will not fire in that case.
server-side:
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('disconnect', function () {
console.log('user disconnected');
});
});
the socket.disconnect() method will not work.
I am trying to use CanDisconnect routing guards but does not know how to use that to close the connection.
server side:
// dependencies
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
//importing routes
var loginRouter = require('./routes/loginRoutes');
var chatRouter = require('./routes/chatRoutes');
app.use('/', loginRouter); // applying routes to the app
app.use('/', chatRouter); // applying routes to the app
// starting the server
http.listen(3000, function(){
console.log('server is listening on port '+PORT);
});
// socket.io ===================================
io_public = io.of('/public'); // namespace public
io_public.on('connection', function(socket){
socket.on('adduser', function(username){
socket.username = username;
socket.room = 'public'; //assign default public room
socket.join(socket.room);
socket.emit('server', 'you have connected to a public room');
socket.broadcast.to('public').emit('server',socket.username + ' has connected to this room');
});
socket.on('disconnect', function(){
socket.broadcast.to('public').emit('server',socket.username + ' has left the room');
socket.leave(socket.room);
});
});
client side:
var socket = io('http://localhost:3000/public');
var user = Cookies.get('user');
socket.on('connect', function(){
socket.emit('adduser', user);
});
socket.on('server',function(msg){
$('#conversation').append('<li> <b>Server: </b>'+msg+'</li>');
});
I am loading this client script in home component on dashboard/home, when user moves to dashboard/contacts it does not disconnect. It also create duplicate socket listeners also because this client script will reloaded every time the component is loaded.
starting state
move to contact routes:
Reloading home component

You can generate an Angular service for connecting and disconnecting. Call the service to Connect on the ngOnInit on the components you want and then call the disconnect method on the ngOnDestroy method.
You can also try to do the same implementing Guards like you said.

Inside component.ts
ngOnInit() {
this.chatService.connect()
}
ngOnDestroy(){
this.chatService.disconnectSocket();
}
Inside ChatService
import { io, Socket } from "socket.io-client";
private socket: Socket;
constructor() {
this.socket = io("http://localhost:4000");
}
connect(){
this.socket.connect()
}
disconnectSocket(){
this.socket.disconnect()
}

Related

Catch "signal" in routing page

I have create a socket in app.js
APP.JS
var app = express();
var server = require('http').createServer(app)
var io = require('socket.io').listen(server);
app.set('socketio', io);
io.sockets.on('connection', function(socket){
console.log('Connesso');
socket.on('message', function(data){
console.log("Oo");
})
})
In my html page I have a js script
newex.onsubmit = function(event){
event.preventDefault();
socket.emit('message', {
name: document.getElementById('name').value,
desc: document.getElementById('description').value
});
}
So, when an user submit a form, the socket should send a "signal", but I want catch the signal in a routing page, not in my app.js
I tried with:
ROUTING PAGE
io = req.app.get('socketio');
io.on('message', function(message){
console.log(message);
})
But it doesn't work! I get that I need to put io.on(...) into io.sockets.on clousure but I don't get why. Can you explain me mechanism of socket.io?
EDIT
I set 'socket' in this way and I try code of tbking but it doesn't work anyway
io.sockets.on('connection', function(socket){
console.log('Connesso');
app.set('socket', socket);
//socket.on('message', function(message){console.log("Ricevuto")})
})
You need to listen to the messages from the specific socket the client is connected to.
Try this in your routing file:
var socket = req._socket;
socket.on('message', function(message){
console.log(message);
})

communicate between two modules nodejs

Hello i am trying to emit command using SOCKET to user when setting gets changed through some API..
but I dont know how can i get socket or tell socket to emit the message to user..
Please Help
this is my code
//Socket INIT
class Socket{
constructor(){
//Init variables
}
start(){
//Start socket
this.io.use((socket, next) => this.auth.authDevice(socket, next));
this.io.on('connection',(socket) => this.conn.handleConn(socket));
}
}
//Socket Connection
let socketStack = [];
class Connection{
handleConn(socket){
// store client
socketStack[socket.userid] = socket
}
pushCmd(userid, command){
//cheeck if userid exists in >>socketStack<< and emit
}
}
//Command Emit
class Command {
constructor(id) {
this.userid = id.userid
//socket - Connection class
this.socketConn = new SocketHandler()
}
static push(userid, command) {
//i want to sent it to current socket context. this has empty socketStack..
this.socketConn.pushCmd(userid, command);
}
}
let socket = new Socket();
socket.start() //connection started, all clients connect to //this socket .. I WANT API to use this socket to emit something that //API sends....
You have to make socket to 'listen' on server. For example, I'm using express with node.js, and this is the way I run socket.io:
var app = express();
var server = require('http').createServer(app);
var io = socketio.listen(server);
io.on('connect', function (socket) {
socket.on('exampleCall', function () {
console.log("socket invoked!");
socket.emit("exampleEmit");
});
});
server.listen(process.env.PORT || 3000, process.env.IP || "0.0.0.0", function () {
var addr = server.address();
console.log("Server listening at", addr.address + ":" + addr.port);
});

How to reuse TCP Client for further use in node.js

I am using a TCP connection via node.js to connect to a certain port in windows, however I want the connection to be established until the user logs out .
In other words I want to add the TCP Connection as a session attribute in node.js ,so that it will last as long as the session is alive for the user.
I have tried this ,but it doesn't work.
Code :
var express = require('express');
var authRouter = express.Router();
var createTCPConnection = function () {
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 6969;
var client = new net.Socket();
client.connect(PORT, HOST, function() {
console.log('CONNECTED TO: ' + HOST + ':' + PORT);
// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
client.write('I am Chuck1 Norris!');
});
// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {
// Close the client socket completely
//client.destroy();
});
// Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});
return client;
};
authRouter.route('/').get(function(req, res) {
var sess = req.session;
if (sess.username) {
//If Session has username attribute, it is a valid session
res.render('dashboard', {
title : 'Welcome To Operator Screen',
username : sess.username
});
if(sess.tcpClient === undefined) {
console.log('Establishing TcpClient');
sess.tcpClient = createTCPConnection();
} else {
console.log('TcpClient already established');
}
} else {
//Invalid/expired session, redirect to homepage
res.redirect('/logout');
}
});
module.exports = authRouter;

socket io changes socket.id repeatedly

Is this normal behavior?
socket.io-1.3.2.js
From the client:
socket = io.connect('https://socket.myserver.nl');
socket.on('connect', function() {
socket.emit('register', userID, 'Lobby');//ignore this
});
At the server Node version v5.2.0:
io.sockets.on('connection', function (socket) {
console.log('SOCKET CONNECTING '+socket.id);
////lots of other code//////////
socket.on('disconnect', function() {
console.log('SOCKET DISCONNECTING '+socket.id);
});
});
During test when i make a single connection with a client to the server and further doing absolutely nothing i get the following (5 minutes approximately):
SOCKET CONNECTING SddHIXmWSeHEfDnlAAAC
SOCKET DISCONNECTING SddHIXmWSeHEfDnlAAAC
SOCKET CONNECTING o0zj7GE1tlO3RQw1AAAD
SOCKET DISCONNECTING o0zj7GE1tlO3RQw1AAAD
SOCKET CONNECTING lAnfvaF3DXMyhc6lAAAE
SOCKET DISCONNECTING lAnfvaF3DXMyhc6lAAAE
SOCKET CONNECTING tP3cjtJ-VpPPjoG2AAAF
SOCKET DISCONNECTING tP3cjtJ-VpPPjoG2AAAF
SOCKET CONNECTING a2o13T7CgcKDEbppAAAG
SOCKET DISCONNECTING a2o13T7CgcKDEbppAAAG
SOCKET CONNECTING avogGTh0KVtLFOqNAAAH
SOCKET DISCONNECTING avogGTh0KVtLFOqNAAAH
SOCKET CONNECTING usoQGxKAMsth2zTcAAAI
SOCKET DISCONNECTING usoQGxKAMsth2zTcAAAI
question continues here: socket-io-changes-socket-id-repeatedly part 2
If you use React, Vue or something like that
Create another js file inside src and type these lines for connecting myCustomSocket.Export socket.id and socket. Because you need to run socket.io out of dynamic rendered components.
import { io } from 'socket.io-client';
export const socket = io('http://localhost:5000');
export let socketID = '';
socket.on('connect', () => {
socketID = socket.id
})
And inside React components you can import them.
import { socketID, socket } from './myCustomSocket';

How to broadcast and get notification using Express, AngularJS, Socket.io?

I am trying to make notification system. To demonstrate this, User 1 is sending friend request to User 2. I am using express.js, angularjs and socket.io. On click of the button User1 sends request. On end of User2, there is a socket,on() which is listening on friend-request event. But when I am broadcasting, the other user is not able to receive any message.
app.js (Node Server File)
var express = require('express'),
app = express();
var port = process.env.PORT || 3000;
var io = require('socket.io').listen(app.listen(port));
require('./config')(app,io);
require('./routes')(app,io);
config.js
// This file handles the configuration of the app.
// It is required by app.js
var express = require('express');
module.exports = function(app, io){
// Set .html as the default template extension
app.set('view engine', 'html');
// Initialize the ejs template engine
app.engine('html', require('ejs').renderFile);
// Tell express where it can find the templates
app.set('views', __dirname + '/views');
// Make the files in the public folder available to the world
app.use(express.static(__dirname + '/public'));
};
routes.js (Emitting Friend Request From this File)
var gravatar = require('gravatar');
var mysql = require('mysql');
// This is needed if the app is run on heroku:
var connection = mysql.createConnection({
host : "localhost",
user : "root",
password : "",
database : "two_way_demo"
});
connection.connect(function(error){
if(error)
{
console.log("Problem with MySQL"+error);
}
else {
console.log("Connected with Database");
}
});
module.exports = function(app,io){
app.get('/',function(req,res){
res.render('index');
});
app.get('/create', function(req,res){
// Generate unique id for the room
var id = Math.round((Math.random() * 1000000));
// Redirect to the random room
res.redirect('/chat/'+id);
});
app.get('/home/:id', function(req,res){
// Render the chant.html view
res.render('home');
});
// Initialize a new socket.io application, named 'chat'
var chat = io.on('connection', function (socket) {
socket.on('get-user-id',function(data){
connection.query("SELECT * from user_info WHERE email='"+data.userEmail+"'",function(err,rows){
if(err)
{
console.log("Problem with MySQL"+err);
}
else
{
//console.log(rows);
JSON.stringify(rows);
socket.emit('user-id',rows);
}
});
});
socket.on('send-request',function(data){
console.log(data);
*********************************************************************
// Tried the emit here but its not working
//io.emit('friend request', {
// receiverid: data.receiverid
//});
*********************************************************************
});
});
}
angular-code.js (angular code file)
$(function () {
var app = angular.module("notificationApp", []);
app.controller("chatCTRL", ["$scope", "$http", "$interval", function ($scope, $http, $interval) {
// connect to the socket
//var socket = io();
//socket.on('connect', function () {
// io.on('friend request', function (data) {
// alert("here")
// });
//});
$scope.senderId = Number(window.location.pathname.match(/(\d+)$/)[1]);
$scope.sendrequest = function (senderid, receiverid) {
var socket = io();
socket.on('connect', function () {
socket.emit('send-request', {
senderid: senderid,
receiverid : receiverid
});
});
}
}]);
app.controller("loginCTRL", ["$scope", "$http", "$interval", "$window", function ($scope, $http, $interval, $window) {
$scope.sendLogin = function () {
var socket = io();
socket.on('connect', function () {
socket.emit('get-user-id', {
userEmail: $scope.hisEmail
});
});
socket.on('connect', function () {
socket.on('user-id', function (data) {
$scope.UserId = data[0].user_id;
$window.location = "http://localhost:3000/home/" + $scope.UserId;
});
});
}
}]);
}());
home.html
<!DOCTYPE html>
<html ng-app="notificationApp">
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body ng-controller="chatCTRL">
<h1>welcome</h1>
<div id="createbutton">
<div id="little"><button ng-click="sendrequest(senderId,6)">Send Friend Request to User#6</button></div>
</div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="../angular/angular.js"></script>
<script src="../angular/common_angular.js"></script>
</body>
</html>
Some client side architecture things:
In most cases on angular client side it is better to move your socket connection to service. And make connection when service is initialized (service is singleton, therefore there will be one connection on start) and inject this service in your controllers.
It may be convenient to create some parent abstract controller with
all socket listeners, therefore whether angular controller is active, all listeners are watching. When parent controller get data from socket it can broadcast it to children controllers
In your commented code you have:
//var socket = io();
//socket.on('connect', function () {
// io.on('friend request', function (data) {
// alert("here")
// });
//});
change it to this (if you make connection in service you should omit connect part):
var socket = io();
socket.on('connect', function () {
socket.on('friend request', function (data) {
alert("here")
});
});
Backend:
In your commented code you have:
//io.emit('friend request', {
// receiverid: data.receiverid
//});
You should use socket's from var chat = io.on('connection', function (socket) {... to emit instead of io.emit
Create array variable where you will store all your sockets with users id before connection part:
var socketList = [];
var chat = io.on('connection', function (socket) {
socketList.push({id:someId,socket:socket})
...
}
Now in send-request user should send id of his frient (we have to know which user should be notified- of course we can notify everybody):
socket.on('send-request',function(data){
socketList.forEach(function(soc){
if(soc.id === someId){
soc.socket.emit('friend request', {
receiverid: data.receiverid
})
}
});
Also i don't like this part receiverid: data.receiverid, because it means that taget user get id of receiver from receiver client side. And this may be unsafe (user can change his id and send some other id). I prefere to create id in server side and when user A send notification to user B I get user A id from server variable.
Some time age I create simple prototype of chat application (angular and express), there are some things which I mention here. I you have still problems with your application go there and check my code :
https://github.com/uhlryk/chat-prototype

Categories

Resources