I really need help getting past this problem I'm facing with socket.io. Believe me, I've looked at just about every post on this topic...
App.js
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('disconnect', function () {
console.log('User Disconnected');
});
socket.on('example_message', (msg) => {
console.log('message: ' + msg);
});
});
app.set('socketio', io);
const port = process.env.PORT || 7777;
app.listen(port);
console.log(`Server listening at ${port}`);
module.exports = app;
Routes.js
const express = require('express');
const router = require('express-promise-router')();
router.route('/test-route')
.put(TestController.testEmit);
module.exports = router;
TestController.js
module.exports = {
testEmit: async (req, res, next) => {
const io = req.app.get("socketio");
console.log(io); // this ACTUALLY logs the entire socketio object!
io.emit('example_message', 'abc'); // NOTHING HAPPENS
}
}
Every time I reload my client, I see the "a user connected" in the terminal window. However, when I attempt to emit from the testEmit controller, nothing ends up happening.
Related
Hello everyone and happy holidays!
I'm creating a chat app using socket.io and Express and need some guidance on how to proceed.
As it is now, I have my socket.io module in the same file as my express js file.
And it works fine, but when I started to implement a login page i noticed that when a go to the "localhost:port/" i still get connected to the socket and i get assigned a socket.id.
And it does make sense, I suppose, to start from the top and go to the bottom.
My plan is:
Go through the login page first
Then get redirected to the "localhost:port/MessagingClient" and get a socket.id
How it works now:
Go to the login page, get assigned a socket.id without login in.
Go to "localhost:port/MessagingClient" and get assigned a new socket.id
But since i run everything in 1 js file it doesn't work as i want it to.
My question is how can I split "Login" page and "MessagingClient" page, but still run on the same port?
I imagine I could solve this by running 2 node js processes instead of 1 and use 2 ports, but is that a valid way of doing it?
MessaginServer.js:
const dotenv = require("dotenv").config();
const express = require("express");
const app = require("express")();
const http = require("http").Server(app);
const io = require("socket.io")(http);
const port = process.env.PORT || 3000;
// import { readFromDB } from "./mongoDB.js";
const { readFromDB } = require("./mongoDB");
app.use(express.static(__dirname + "/public/"));
app.get("/", (req, res) => {
res.sendFile(__dirname + "/Public/LoginClient.html");
});
app.get("/MessagingClient", (req, res) => {
res.sendFile(__dirname + "/Public/MessaginClient.html");
});
io.on("connection", async (socket) => {
// socket.on("test1", arr1, arr2)=>{};
// socket.on("test2", arr1, arr2)=>{};
})
http.listen(port, () => {
console.log(`Socket.IO server running at http://localhost:${port}/`);
});
What i have tried:
I tried to move all the socket.io code inside
app.get("/MessagingClient", (req, res) => {
res.sendFile(__dirname + "/Public/MessaginClient.html");
});
but that resulted in message duplication..
Then I thought about trying to use Npm concurrently, but could not find anything about whether it is okay to use it in a production environment.
Any tips?
you create a socket server in a separate file:
const socketServer = (server) => {
const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
//set middleware for socket server here before .on
io.use((socket, next) => {
yourMiddleware(socket, next);
});
// your io connection logic
io.on("connection", async (socket) => {
// socket.on("test1", arr1, arr2)=>{};
// socket.on("test2", arr1, arr2)=>{};
});
};
module.exports = {
socketServer,
};
then in app.js
//initialize app
const app = express();
// add your middlewares and routing
const server = http.createServer(app);
// import socketServer
socketServer(server);
server.listen(PORT, () => {
console.log(`Server is listening on ${PORT}`);
});
you create a socket server in a separate file:
const socketServer = (server) => {
const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
//set middleware for socket server here before .on
io.use((socket, next) => {
yourMiddleware(socket, next);
});
// your io connection logic
io.on("connection", async (socket) => {
// socket.on("test1", arr1, arr2)=>{};
// socket.on("test2", arr1, arr2)=>{};
});
};
module.exports = {
socketServer,
};
then in app.js
//initialize app
const app = express();
// add your middlewares and routing
const server = http.createServer(app);
// import socketServer
socketServer(server);
server.listen(PORT, () => {
console.log(`Server is listening on ${PORT}`);
});
I am very new to this socket programming. I got confused when to use io and socket in below code. Here, when a new user connects to the server and listens to any events then we use socket.on for that but while sending back response we use io.emit, cant we use socket.emit here? and what is the difference between them?
const express = require('express');
const app = express();
const PORT = 4000;
const http = require('http').Server(app);
const cors = require('cors');
app.use(cors());
const io = require('socket.io')(http, {
cors: {
origin: "http://localhost:3000"
}
});
let users = [];
io.on('connection', (socket) => {
console.log(`⚡: ${socket.id} user just connected!`);
socket.on('newUser', (data) => {
users.push(data);
io.emit('newUserResponse', users);
});
socket.on('message', (data) => {
console.log(data);
io.emit('messageResponse', data);
});
socket.on('disconnect', () => {
console.log('🔥: A user disconnected');
users = users.filter((user) => user.socketID !== socket.id);
io.emit('newUserResponse', users);
socket.disconnect();
});
});
app.get('/api', (req, res) => {
res.json({
message: 'Hello world',
});
});
http.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
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");
});
I'm pretty new to sockets and I've been struggling to implement some of the documentation i've seen online. This is my set up currently and I wanted to run socket.io against just the healthcheck api endpoint (/api/v1/healthcheck) how would I go about running socket io in the healthcheck controller? and emit changes to the response? Any help is appreciated, i'm tearing my hair out :(
Server.js
const socket = require('socket.io')
const healthcheck = require('./routes/healthcheck');
const auth = require('./routes/auth');
const users = require('./routes/users');
const server = app.listen(
PORT,
console.log(
`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.cyan.bold
)
);
let io = require('socket.io')(server);
app.set("io", io);
//Auth
app.use('/api/v1/auth', auth);
app.use('/api/v1/users', users);
//Health check
app.use('/api/v1/healthcheck', healthcheck);
/routes/healthcheck.js
const express = require('express');
const { checkHealth } = require('../controllers/healthcheck');
const router = express.Router();
router.post('/', checkHealth);
module.exports = router;
/controllers/healthcheck.js
const asyncHandler = require('../middleware/async');
exports.checkHealth = asyncHandler(async (req, res, next) => {
res.status(200).json({
success: true,
data: {
status: "Alive!"
}
});
});
You can pass in the instance of io into that healthcheck route and then simply listen to events and take action. Sample code below.
server.js
const socket = require('socket.io')
const server = app.listen(
PORT,
console.log(
`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.cyan.bold
)
);
let io = require('socket.io')(server);
app.set("io", io);
// pass in io to the relevant route
const healthcheck = require('./routes/healthcheck')(io);
const auth = require('./routes/auth');
const users = require('./routes/users');
//Auth
app.use('/api/v1/auth', auth);
app.use('/api/v1/users', users);
//Health check
app.use('/api/v1/healthcheck', healthcheck);
healthcheck route
const express = require('express');
const { checkHealth } = require('../controllers/healthcheck');
const router = express.Router();
module.exports = (io) => {
router.post('/', checkHealth);
io.on('connection', socket => {
socket.emit('hello', {message: 'helloworld'});
socket.on('reply', checkHealth.someMethod);
});
return router;
}
I would rather create endpoints in files - same as you do for express routes, and init these in your server.js as follows:
let io = require('socket.io')(server);
app.set("io", io);
io.on('connection', socket => {
require('./myendpointexample')(socket);
});
myendpointexample.js
module.exports = (socket) => {
socket.on('myevent', (message) => {
mycontroller.myFunction(message).then(result => {
socket.emit('myEvent', result);
});
});
};
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