Reactjs / Express: socket.io is not getting messages - node.js

The frontend is Reactjs:
componentDidMount(){
const socket = io.connect('ws://127.0.0.1:3001');
socket.on("connect", () => {
console.log('socket on connect; socket.id: ', socket.id); // Never printed!
});
socket.on("disconnect", () => {
console.log('socket on disconnect; socket.id: ', socket.id);
});
socket.on("hello", (res) => {
console.log('on hello: ', res); // Never printed!
});
socket.on("thank", (res) => {
console.log('on thank: ', res); // Never printed!
});
socket.emit("thank", "you");
};
The backend is Typescript / Express:
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded());
app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'build')));
... some custome middleware
var server = app.listen(3001);
// ------------------- configure Socket.io -------------------------
var io = require('socket.io').listen(server);
io.on("connection", function(socket: any) {
console.log("a user connected. socket: ", socket); // Never printed!
socket.emit('hello', 'world')
socket.emit('thank', 'you')
socket.on("thank", (res) => {
console.log('on thank: ', res); // Never printed!
});
});
// ----------------------------------------------------------------
I was hoping to send "world" and "you" on message "hello" and "thank" both from client to server and from server to client.
However, the line console.log("a user connected. socket: ", socket); was never executing on the server side.
Also the line console.log('socket on connect; socket.id: ', socket.id); was never printing on the client side.
Not to mention the "hello world" or "thank you" messages.
Moreover, I see a request of the form :
http://127.0.0.1:3001/socket.io/?EIO=4&transport=polling&t=Nk3yMzc
being made constantly and results in 404 not found
Question:
what is this GET request /socket.io/?EIO=4&transport=polling&t=****? What does it do? Why does it fire constantly?
The Express log is showing error:
RouteNotFoundError: Route '/socket.io/?EIO=4&transport=polling&t=Nk3zIhW' does not exist.
How can I solve this?
I'm making the Express app and the websocket share the port 3001. Some middlewares are designed for HTTP requests, and they are not for the websocket message. How can I make the websocket messages avoid the express middlewares?

The .listen function in your code below is to attach an httpServer to an already started WS server.
var io = require('socket.io').listen(server);
I think this should be:
var io = require('socket.io')(server);

Related

Socket.io emit not working (by visiting URL)

I am developing an app that gets a signal from external hardware equipment. I catch this signal by redirecting it to a certain URL in my app: '/impulse/:id'.
I am able to catch the signal, but the emit function inside the app.get('/impulse/:id') is not triggering. The console logs are...
How can I make the emit function work?
Below is my server.js script, where I catch all the socket signals and prevent the external call from being redirected to the index page.
...
const express = require('express');
const app = express();
const port = process.env.PORT || 8080;
const socket = require('socket.io');
app.use(express.static(__dirname + '/public'));
app.use('/api', appRoutes);
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://HERE IS MY DB INFO...', function(err) {
if (err) {
console.log('Not connected to the database: ' + err); // Log to console if unable to connect to database
} else {
console.log('Successfully connected to MongoDB'); // Log to console if able to connect to database
}
});
var server = app.listen(port, function() {
console.log('Running the server on port ' + port); // Listen on configured port
});
var io = socket(server);
io.on('connection', function(socket){
socket.on('join', function(data){
var gameroom = data.gameid;
console.log("joined: " + gameroom)
socket.join(gameroom);
})
//FUNCTION I WANT TO TRIGGER
socket.on('impulse', function(data){
console.log('IMPULSE')
io.emit('impulseReceived', {
})
})
})
//PLACE WHERE I EMIT
app.get('/impulse/:id', function(req, res){
console.log('Impulse Received')
var time = req.query.TIME;
var gameroom = req.params.id;
io.on('connect', function (socket) {
socket.emit('impulse', {
})
})
res.json({ success: true, message: 'received the time!'})
})
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html')); // Set index.html as layout
});
Replace this whole
io.on('connect', function (socket) {
socket.emit('impulse', {
})
}
with this
io.emit('impulse', {})

Prevent closing connection on bad request

I have an express server.
I set socket.setKeepAlive(true, 60000); in order to maintain persistent connection for at least 1min.
Here is the code:
var express = require("express");
var app = express();
var server = app.listen(8080);
app.get("/", (req, res) => {
res.write("Hello Riko");
});
// server.listen(3000);
server.on("connection", function(socket) {
console.log("A new connection was made by a client.");
socket.setKeepAlive(true, 60000);
socket.on("data", data => {
console.log(data);
});
// 30 second timeout. Change this as you see fit.
});
When the client send invalid request, it receives 400 Bad Request
How to prevent connection close on invalid request?
Yes the suggestion i made in the comments works.
server.on('clientError',cb) prevents the default behavior of the stack.
I encountered one problem though. It registers event listener for error event every time clientError is fired. Therefore I changed the code litle bit and ended up with a solution that works for me:
var express = require("express");
var app = express();
var server = app.listen(8080);
app.get("/", (req, res) => {
res.send("Hello Riko");
});
onSocketError = err => {
console.log("Socket Error: " + err);
};
server.on("connection", function(socket) {
socket.on("data", data => {
console.log(data.toString());
});
console.log("A new connection was made by a client.");
});
server.on("clientError", (err, socket) => {
socket.removeAllListeners("error");
});
Hope this would help someone with similar problem.

Express websockets on message get cookie info

I have an express web socket application.
In the onmessage function, I would like to access the cookies of the client that sent the message.
The reason for this is that I'm making a game and I have the user login. I need to check what to name cookie is so that I control the correct player.
This is what I've got so far:
var express = require('express');
var expressWs = require('express-ws');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
app.use(cookieParser('secretkey123'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}))
expressWs = expressWs(app);
app.get('/', function(req, res) {
// stuff for logging in
})
app.post('/', function(req, res) {
// stuff for logging in
})
app.get('/logout', function(req, res) {
res.clearCookie('name');
res.redirect('/');
// more stuff for logging in
})
app.ws('/ws', function(ws, req) {
ws.on('open', function() {
// how do I check when a connection is opened?
})
ws.on('message', function(msg) {
// who sent the message? how do I get the cookie info to check the user who send it?
})
ws.on('close', function() {
// the've disconnected
})
})
var server = app.listen(8000, function () {
var host = server.address().address
var port = server.address().port
})
Is this possible?
Also, where do I check when a websocket connection is opened?
I tried the 'open' event but it doesn't seem to be working.
Thanks for the help in advance!
I figured out how to do it!
I forgot that the req argument can be accessed inside the other functions.
This means in the on message function you can just do this:
ws.on('message', function(msg) {
req.cookies.username //do stuff
});
The connection open code can be done before you setup any of the events:
app.ws('/ws', function(ws, req) {
// connection open code here
ws.on('message', function(msg) {
// connection message code here
})
})

Can't seem to get socket io to display any emits

I've been trying to figure out why I can't get any emits to show up in my terminal and it seems that everything is running fine.... except for seeing the emits. Here is my code
var express = require('express');
var path = require('path');
// Create a new Express application
var app = express();
var views = path.join(process.cwd(), 'views');
app.use("/static", express.static("public"));
// Create an http server with Node's HTTP module.
// Pass it the Express application, and listen on port 3000.
var server = require('http').createServer(app).listen(3000, function() {
console.log('listening on port ' + 3000)
});
// Instantiate Socket.IO hand have it listen on the Express/HTTP server
var io = require('socket.io')(server);
var game = require('./game');
app.get('/', function(req,res) {
res.sendFile(path.join(views, 'index.html'));
});
io.on('connect', function(socket) {
io.emit('connection', { message: "You are connected!" });
game.initGame(io, socket);
socket.emit('connected', { message: "You are connected!" });
io.sockets.emit('test', 'test')
});
Any help would be great!
Emits are not automatically printed. socket.emit will send a message back to the client, not to the terminal. Use console.log("whatever") to print to the terminal:
io.on('connect', function(socket) {
console.log('Client connected');
socket.on('test', function(data) {
console.log("Got message of type 'test'containing data:", data);
});
});

duplicate message received on redis sub

I am using express 3x, node.js and redis. when i as publishing message then 1 have receive this message 2-3 times in subscribe. (e.g. when i am refreshing my browser, message receive increase by 1 each time) .
below is my code.
server side :
~~~~~~~~~~
var express = require('express'),
http = require('http')
var redis = require('redis');
var redisCli = redis.createClient();
var redisPub = redis.createClient();
var redisSub = redis.createClient();
redisCli.on("error", function (err) {
console.error("\r\n Error generated from redis client ", err);
});
redisPub.on("error", function (err) {
console.error("\r\n Error generated from redisPub ", err);
});
redisSub.on("error", function (err) {
console.error("\r\n Error generated from redisSub ", err);
});
var server = http.createServer(app)
, io = require('socket.io').listen(server);
server.listen(process.env.PORT);
app.configure(function () {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set('view options', { layout: false });
app.use(express.favicon(__dirname + '/favicon.ico', { maxAge: 2592000000 }));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: "myKey", store: new RedisStore({ maxAge: 86400000, client: redisCli }), cookie: { maxAge: 86400000} }));
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/static'));
});
io.configure(function () {
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.enable('browser client gzip'); // gzip the file
io.set('log level', 1);
io.set("flash policy server", false);
io.set("transports", ["jsonp-polling", "xhr-polling"]);
});
io.sockets.on('connection', function (client) {
console.log("server - redisSub.subscribe from io.on.connection");
redisSub.unsubscribe();
redisSub.subscribe("announcement");
redisSub.on("message", function (channel, message) {
io.sockets.emit('announcement', message);
});
client.on('disconnect', function () {
redisSub.unsubscribe("announcement");
redisSub.quit();
});
});
app.post('/PublishMessage', function (req, res) {
redisPub.publish("announcement", req.body.users);
res.setHeader('Cache-Control', 'max-age=0, must-revalidate, no-cache, no-store');
res.setHeader('Connection', 'keep-alive');
res.contentType('application/json');
res.setHeader('Expires', new Date().addYears(-10));
res.json({ result: 'ok' });
});
Client side
~~~~~~~~~
this.socket = io.connect('http://XXX.XXX.X.XXX/', { transports: ['jsonp-polling', 'xhr-polling'] });
this.socket.on('connect', function () {
alert("client - Socket client connect");
});
this.socket.on('announcement', function (msg) {
alert("clientside - announcement ");
var nUsers = parseInt($('#Summary>article>p:last').text(), 10) + parseInt(msg, 10);
$('#Summary>article>p:last').text(nUsers);
});
=================================================================
So, any one guide me for the same !!!
thank you very much.
I have never used socket.io, but it looks to me like you're over complicating things with your connection handler.
Inside the handler, it doesn't seem like you're reacting to the connection (like emitting a "user connected" event) or modifying the behavior of the individual socket connection in any way.
What you are doing, is repeatedly subscribing and unsubscribing the one redisSub client. I could be wrong here, but I don't think you need to or should be doing that.
Rather you should sub "announcement" once, outside of the connection handler, as you don't need to sub/unsub this global client on every connection. Like:
// Move this subscription outside of the connection handler, and you shouldn't
// have to continue to sub/unsub or otherwise manage it.
redisSub.on("message", function (channel, message) {
io.sockets.emit('announcement', message);
});
// Since you're not reacting to connections or doing anything with individual
// connection sockets, you don't really have anything to do in this handler.
io.sockets.on('connection', function (socket) {
// if you ONLY wanted to emit to this socket, you'd do it here
//socket.emit("announcement", "just for this connection")
});

Resources