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}`);
});
Related
I have a problem with using socket.io in my application.
I use Next.js, Express.js, socket.io, socket.io-client
When I run Next.js server and Express server then access the page, socket is immediately connected. But when I post to /webhook/notify from other server socket.emit("notify", req.body); does not work. But when I reload the backend server, somehow it works for no reason.
Below are my codes
Frontend side
const socket = io.connect("http://127.0.0.1:3000", { cors: true }); //backend server
socket.on("connection", async (data) => { // it works
try {
console.log(data);
} catch (err) {
console.error(err.response);
}
});
socket.on("notify", async (notify) => { // it does not works while I reload backend server
try {
console.log(notify);
} catch (err) {
console.error(err.response);
}
});
Backend side
index.js
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors({ origin: "http://127.0.0.1:3060" }));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
const Socket = require("./socket");
const server = app.listen(PORT, function () {
return console.log("Backend server listening on port" + PORT);
});
Socket(server, app);
socket.js
const Socket = require("socket.io");
const axios = require("axios");
module.exports = (server, app) => {
const io = Socket(server, {
cors: {
origin: "*",
},
});
io.on("connection", (socket) => {
console.log("socket is connected");
app.post("/webhook/notify", (req, res, next) => {
try {
socket.emit("notify", req.body);
} catch (err) {
console.error(err.response);
return next(err);
}
});
socket.on("disconnect", () => {
console.log("disconnected");
});
});
};
I am attempting to create a server that will accept a post request (coming from a flutter app) containing the name of a song. I then want the server to broadcast the name of that song to all listening clients.
I've tried a dozen ways to do this and nothing seems to work. I've tried using express and flask, but to no avail. Here's where I'm at right now, but obviously this doesn't work because I can't get the script to start both the socket server (using npm start) and api (using node index.js) at the same time. You'll also notice that I'm not currently sending a song name, just trying to send a time to start.
'use strict';
const port = process.env.PORT || 3000;
const express = require('express');
const { Server } = require('ws');
const PORT = process.env.PORT || 3000;
const INDEX = '/index.html';
const server = express()
.use((req, res) => res.sendFile(INDEX, { root: __dirname }))
.listen(PORT, () => console.log(`Listening on ${PORT}`));
const wss = new Server({ server });
wss.on('connection', (ws) => {
console.log('Client connected');
ws.on('close', () => console.log('Client disconnected'));
});
setInterval(() => {
wss.clients.forEach((client) => {
client.send(new Date().toTimeString());
});
}, 1000);
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.post('/', (req, res) => {
wss.clients.forEach((client) => {
client.send(new Date().toTimeString());
});
res.send('POST request reached server');
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
I have an Electron project initiated with VueCLI and a litle nodejs socket.io server, here's the server's file :
const http = require('http');
const express = require('express');
const socketio = require('socket.io');
const {
userJoin,
getCurrentUser,
userLeave,
getRoomUsers,
users
} = require('./utils/users');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
// Run when client connects
io.on('connection', socket => {
console.log(`Connected tp ${socket.id}`)
app.get('/send-file', (req, res, next) => {
res.send('Sent')
})
socket.on('joinRoom', (args)=>{
console.log('joinroom')
})
// Runs when client disconnects
socket.on('disconnect', () => {
const user = userLeave(socket.id);
});
});
const PORT = process.env.PORT || 7575;
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
And here's my preload.js file :
const io = require('socket.io-client');
window.socket = io('http://localhost:7575');
window.socket.on('welcome', () => {
console.log('on welcome : welcome received renderer'); // displayed
window.socket.emit('test')
});
window.socket.on('error', (e) => {
console.log(e); // displayed ?
});
window.socket.on('ok', () => {
console.log("OK received renderer"); // displayed
});
window.socket.on('connect', () => {
console.log("connected renderer"); // displayed
window.socket.emit('test');
});
And here's my createWindow function:
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 700,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
enableRemoteModule: true,
preload: path.join(__dirname, 'preload.js')
}
})
win.setMenu(null)
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
}
The connection is made between the client and the server, because the console.log(Connected tp ${socket.id}) show a different socket ID everytime, but on my compenent, when I call the emit function nothing happens : window.socket.emit('joinRoom', {email:this.email, apikey:this.apikey})
And I can't event receive message on the client side, I've tested the server and everything works fine on a normale browser, but on my electron application can't emit or receive messages.
Is this related to my electron application?
Here's how I did it -
Server side:
const express = require('express')
const app = express()
// middlewares
app.use(express.static('public'))
// routes
app.get('/', (req, res) => {
res.render('index')
})
server = app.listen(7575, () => {
console.log("Server started");
})
//socket.io instantiation
const io = require("socket.io")(server)
//listen on every connection
io.on('connection', (socket) => {
console.log('New user connected');
//listen on "test"
socket.on('test', (data) => {
var username = data.username;
})
})
Client side:
socket = io.connect('http://localhost:7575')
socket.emit('test', {username: 'username'})
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 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.