How to separate Socket.IO events from server.js? - node.js

I created Express, Node, React app.
Now, i want to integrate socket.io to the app.
I searched all over the internet and i found that all the socket.io events are in the initial server.js/app.js file.
But, i want to separate the socket.io events from the main file and then import it to the main file, just like routes/controllers files.
My code right now:
var app = require("express")();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
const mongoose = require("mongoose");
const stocks = require("./routes/stockRoutes");
const bodyParser = require("body-parser");
const cors = require("cors");
const port = 5000;
app.use(stocks);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.set("socketio", io);
const uri =
"mongodb+srv://admin:admin1234#investockcluster0.jp2wh.mongodb.net/<stocks_data>?retryWrites=true&w=majority";
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDB database connection established successfully");
});
io.on("connection", (socket) => {
socket.emit("hello", "world");
console.log("New Connection");
});
http.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});
I want that this code will be in file like "socketEvents.js" and then require it.
io.on("connection", (socket) => {
socket.emit("hello", "world");
console.log("New Connection");
});
Thanks a lot :)

Just put your socket.io code in another module and pass in the server in an initialization method:
// in sock.js
module.exports = function(server) {
const io = require("socket.io")(server);
io.on("connection", (socket) => {
socket.emit("hello", "world");
console.log("New Connection");
});
// put other things that use io here
}
Then, in your main file:
require('./sock.js')(http);
FYI, http is a crummy variable name for your server. You really ought to name it server.

Related

WebSocket connection to 'ws://localhost:5000/socket.io/...' failed: Error during WebSocket handshake: Unexpected response code: 400

I am trying to create a chat app which, uses a real-time database with MongoDB and Websocket.
This is my first React, MongoDB, and Websocket Project, so please excuse possible trivialities. :D
I am currently working on creating a new user, refreshing the database, and finally displaying the created user in every user's frontend in real-time.
Creating and saving a new user works fine and also logging the new user's data in real-time after the database changed (via socket.io) is working as well. Now, I would like to access the information that the database changed in the frontend of my app, so I can refresh the unordered list of users. Now there is the problem I'd like to solve: I try to connect the frontend with my backend by using this code:
//...
import socketIOClient from "socket.io-client";
const ENDPOINT = "localhost:5000";
const MainContentArea = () => {
useEffect(()=>{
const socket = socketIOClient(ENDPOINT);
socket.on("changes", data => {
console.log(data);
})
});
//...
The following is my backend code:
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const index = require('./routes/index');
const port = process.env.PORT || 5000;
const app = express();
app.use(index);
const server = app.listen(port, () => {
console.log(`Server ist running on port: ${port}`);
})
const io = socketIo(server).listen(server);
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config({
path: './.env'
});
const Users = require('./models/user.model');
app.use(cors());
app.use(express.json());
const usersRouter = require('./routes/users');
app.use('/users', usersRouter);
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
},
function(err){
if(err){
console.log("server.js err line 44");
throw err;
}
io.on('connection', (socket) => {
console.log('user connected');
socket.on('disconnect', (socket) => {
console.log('user disconnected');
})
})
Users.watch().on('change', (change) => {
console.log('socket says: something changed in db');
console.log('change: ', change.fullDocument);
io.to(change.fullDocument).emit('changes',change.fullDocument)
})
}
);
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDB database connection established successfully");
})
I keep getting the Error message:
WebSocket connection to 'ws://localhost:5000/socket.io/? EIO=3&transport=websocket&sid=33wU6D8PnqclT3iZAAAB' failed: Error during WebSocket handshake: Unexpected response code: 400
I am using Chrome and I am working on MacOS.
I am very thankful for any suggestions that might help solve my problem.
I hope, how I posted my question is helpful for anybody who is willing to help me with this. If not, feel free to give me suggestions on what to do better next time! This is my first post here.

Sending Object to group of users Node.js by using Socket.IO

I am using Node.js with Express.js and for realtime data I am using socket.io.
I am trying to create on booking app.
So when the user will request through REST api the server will store the information to mongoDB via mongoose and after that the same data will be send to other users.
I am using router for different paths. below is my server.js
var express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const routes = require('./routes/routes');
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors())
app.use(express.urlencoded({ extended: false }));
app.set('socketio', io);
app.use(routes);
mongoose.Promise = global.Promise;
mongoose.connect(
'mongodb://localhost:27017/myapp',
{ useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, }
).then(() => {
console.log('db connected');
}).catch(err => {
console.log(err,"hello 1998");
});
server.listen(8080);
And below is my route
const { Router } = require('express');
var router = Router();
const { main } = require('../helper/db_main')
const { checkAuthentication } = require('../helper/auth')
router.use('/api/v1/services',main,checkAuthentication,require('../controllers/services'));
router.use('/api/v1/category',main,checkAuthentication,require('../controllers/category'));
router.use('/api/v1/socket',main,checkAuthentication,require('../controllers/socket'));
module.exports = router;
and below is the place where I am trying to send/emit data to specific user but it is not working on client side i.e not able to see emit message on front-end side.
const list_all_category = (req,res) => {
console.log("Hjdnckjsdck")
var io = req.app.get('socketio');
// global.io.to("notify_me").emit("message", "hello ftomr");
let result_data
category.list_all_category().then(save_res => {
if (save_res)
result_data = res.status(200).send(save_res)
else{
result = 'fail'
res.send()
}
})
console.log("Here is ninja",io.id)
io.on('connection', function(socket){
console.log(socket.id); // same respective alphanumeric id...
})
io.sockets.on('connect', function(socket) {
const sessionID = socket.id;
})
io.on('notify',function(){
console.log("Galgotia")
})
io.sockets.emit('chat_message', 'world');
}
make use of this
socket.broadcast.to('ID').emit( 'send msg', {somedata : somedata_server} );
you can het each socket id for a specific user by using ${Socket.id}
If you are emitting anything always send the socket.id of a user to the client and send them back to the server.

ExpressJS: localhost didn’t send any data

I am writing an app, when I start the server, its working nicely, its connecting to database. But when I start http://localhost:5000 from the browser, it does not respond for a minuite then the browser shows a message:
localhost didn’t send any data.
ERR_EMPTY_RESPONSE
Here is my app.js:
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
app.use(cookieParser);
app.use(express.json());
//const userRouter = require('./routes/user');
//app.use('/user', userRouter);
const startApp = async () => {
try {
await mongoose.connect('mongodb+srv://username:pass#cluster0-dcytp.mongodb.net/test?retryWrites=true&w=majority',
{ useUnifiedTopology: true,useNewUrlParser: true });
console.log(`successfully connected to database`);
const port = process.env.PORT || 5000
app.listen(port, () => {
console.log(`server runnin at ${port}`);
});
} catch (error) {
console.log(error.message)
}
}
startApp();
app.get('/', (req, res) => {
console.log("I am in the root");
res.send("hello World");
})
Why server is not responding from the browser?
try
app.use(cookieParser())
instead of
app.use(cookieParser)
Reference
I had the same problem db is connected but not able to send data. it looks weird but it works for me.
Add a new database user with new password, use the new userName and passw to connect your mongoodb
this is the exact like to add new database user
here is my db connection may it helps you too
mongoose.connect(DATABASE_URL, { useNewUrlParser: true,useUnifiedTopology: true })
const db = mongoose.connection
db.on('error', (error) => console.error(error))
db.once('open', () => console.log('connected to database'))
app.use(express.json())

Node net.Socket emit data to all connected clients

guys, I'm trying to make simple TCP server with net.Socket package I'm using the express framework.
The behaviour that Im trying to achieve is when user enters specific route to emmit data to all connected clients, doesn anyone now how could I achieve this ??
Here is my sample code:
const express = require('express');
const app = express();
const cors = require('cors');
const bodyParser = require('body-parser');
const net = require('net');
const PORT = 5000;
let connection;
const server = net.createServer((socket) => {
console.log('CONNECTED: ' + socket.remoteAddress +':'+ socket.remotePort);
connection = socket;
});
app.use(cors());
app.use(bodyParser.json());
app.get('/', (request, response) => {
response.send('VMS server');
});
app.post('/contact', (req, res) => {
const data = { hello: 'hello' }
connection.write(data);
res.send({ data: 'data emmited' })
});
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);
});
server.listen(1337, function() {
console.log("Listening on 1337");
});
The problem m having here is that data is gettings emitted multiple times, because Im assigning current socket to connection variable.
Is there any other way how I can do this, could I use server variable to emit to all connected clients somehow ?
Ok, managed to solve it. Here are steps on how I solved it - create an array of clients, & when a client connected to the server , push that socket to client array when disconnected remove that item from the array... And to emit data to all clients, I created a broadcast method where I loop through client array, and call the emit method of each socket & send data.
Here is a sample code:
const express = require('express');
const app = express();
const cors = require('cors');
const bodyParser = require('body-parser');
const net = require('net');
const PORT = 5000;
let sockets = []; // array of sockets
// emmit data to all connected clients
const broadcast = (msg) => {
//Loop through the active clients object
sockets.forEach((client) => {
client.write(msg);
});
};
const server = net.createServer((socket) => {
console.log('CONNECTED: ' + socket.remoteAddress +':'+ socket.remotePort);
sockets.push(socket);
socket.on('end', () => {
console.log('DISCONNECTED: ');
// remove the client for list
let index = sockets.indexOf(socket);
if (index !== -1) {
console.log(sockets.length);
sockets.splice(index, 1);
console.log(sockets.length);
}
});
});
app.use(cors());
app.use(bodyParser.json());
app.get('/', (request, response) => {
response.send('VMS server');
});
app.post('/contact', (req, res) => {
const data = { hello: 'hello' }
broadcast(data); //emit data to all clients
res.send({ data: 'data emmited' })
});
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);
});
server.listen(1337, function() {
console.log("Listening on 1337");
});

How to send message to frontend in case of MongoDb connection Failed

Is there any way to send error to frontend on mongoDb connection error.I had tried in a different different way but I didnt get a solution.
var express = require('express');
var session = require('express-session');
var MongoDBStore = require('connect-mongodb-session')(session);
var store = new MongoDBStore(
{
uri: config.connectionString,
collection: 'tbl_session'
});
// Catch errors
store.on('error', function(error) {
app.get('/',function(req,res){
res.send('NOT Connected....')
});
});
You can use web sockets to push this information to the UI.
const express = require('express');
const app = express();
const path = require('path');
const server = require('http').createServer(app);
const io = require('../..')(server);
const port = process.env.PORT || 3000;
var session = require('express-session');
var MongoDBStore = require('connect-mongodb-session')(session);
var store = new MongoDBStore(
{
uri: config.connectionString,
collection: 'tbl_session'
});
// Catch errors
store.on('error', function(error) {
socket.emit('mongodb-failed', error)
});
});
server.listen(port, () => {
console.log('Server listening at port %d', port);
});
// Routing
app.use(express.static(path.join(__dirname, 'public')));
io.on('connection', (socket) => {
// when socket emits 'mongodb-connection-failed', this listens and executes
socket.on('mongodb-failed', (data) => {
// we tell the client to execute 'new message'
socket.broadcast.emit('mongodb-connection-failed', {
errorDetails: data
});
});
});
now at client side:
var socket = io();
socket.on('mongodb-connection-failed', () => {
console.log('you have been disconnected');
//do more whatever you want to.
});
This above example is using socket.io.
You can use any web socket library, see more here

Resources