One specific "socket.on()" doesn't work on client side - node.js

Server receive message from socket.emit("Wiadomosc"), but client doesn't,
but when I emit message from server io.emit("Wiadomosc"), client receive message;
There is no errors, others socket.emit() socket.on() works fine
I tried everything: copied everything from working functions and nothing.
I think that there is something wrong with me and not with code
Okey, client side:
socket = io.connect("localhost:4000", {
transports: ['websocket']
});
socket.on("Wiadomosc", function () {
console.log("wd");
});
socket.on("gotowosc", function () {
$(".gotowosc").css("display", "block");
});
//somewhere else in code
console.log(socket) //to see if it's fine, and it is
socket.emit("Wiadomosc");
the second one works fine
server side:
let express = require("express");
let app = express();
let server = app.listen(4000, function () {
console.log("listening on port 4000");
});
let socket = require("socket.io");
let io = socket(server);
io.on("connection", function (socket) {
socket.on("Wiadomosc", function () { //I did something like that to check if emit works, and it works
console.log("fine");
});
});
io.emit("gotowosc");

Emitting from a client sends to the server, not to any other client. If you want to send a message from one client to all clients, you send a message to the server and then code the server to receive it and send it to other clients.

Related

SocketIO send message to client via API route

I have a route in my express API where I want to emit messages using a websocket to a client. In this case, the client is another Node.js app. In this Node.js app, I try to connect to the socket and print messages received. Both the API and the Node app are on different ports. Can someone help me make this work?
Here's how I pass my socket to my express routes:
const server = app.listen(PORT, () => {
console.log(`Server on port ${PORT}`);
});
const io = require("socket.io")(server);
app.set("socketio", io);
Here's my REST API route:
exports.getAll = function(req,res){
var io = req.app.get('socketio');
io.emit('hi!');
}
Here's my socket io client, it uses socket.io-client
const socket = io('http://localhost:3000');
socket.on("message", data => {
console.log(data);
});
Unfortunately, I don't receive the 'hi' message from my API.
When I call /api/getAll I don't receive the message in my client app.
When emitting an event via socket.io you have you define the event name before the data.
Example:
exports.getAll = function(req, res){
var io = req.app.get("socketio");
io.emit("message", "hi!");
}
Now you'll be able to receive the message event from the client.
Reference:
https://socket.io/docs/v4/emitting-events/

ExpressJs - SocketIo.client - emit not working

I am trying to connect to the crypto compare's api websockets to get the up to date prices for crypto currencies. I am using expressjs for my server and socketio to connect to crypto compare.
However after logging connected nothing else seems to happen.
This is my first time trying to play with sockets so I am a little lost as to why the io.emit function is not triggering anything.
Also there seems to be an issue in the callback of connect as socket is undefined!
Why does emit not seem to be doing anything?
My app.js file:
const express = require('express');
const app = express();
const clientIo = require('./lib/client-socket/crytpto-compare-socket');
clientIo.connect();
app.disable('x-powered-by');
module.exports = app;
Crypto-compare-socket.js
const io = require('socket.io-client');
const configs = require('./../config/configs');
const crytpCompareConfigs = configs.get('CRYPTO_COMPARE_API');
const cryptoCompareEndpoint = crytpCompareConfigs.ENDPOINT;
const cryptoCompareSocket = io(cryptoCompareEndpoint, {reconnect: true});
cryptoCompareSocket.on('connect', (socket) => { // socket here is undefined
console.log('Connected');
cryptoCompareSocket.emit('SubAdd', { subs: crytpCompareConfigs['LIST_OF_ITEMS']});
});
cryptoCompareSocket.on('SubAdd', (from, msg) => {
console.log('Hello');
console.log(from);
console.log('*******');
console.log(msg);
});
module.exports = cryptoCompareSocket;
The code you are using is client side code. This code does not return a socket in the callback because the client already knows the socket its connected with.
You are subscribing to a socket service, but you do not have any code that responds to data sent from that service.
When crypto compare returns data it sends the "m" event. So you need to respond to "m".
An example
cryptoCompareSocket.on("m", function(message) {
console.log(message);
});

How to handle io.use middleware to capture errors on client?

I need to check authentication for my socket connection and drop one if they failed. My server and client codes looks like the following;
// server.js
var http = require('http');
var sio = require('socket.io');
var app = require('express')();
var server = require('http').createServer(app).listen(3000, function () {
console.log('Server listening on 3000 port');
});
var io = sio.listen(server);
io.use(function (socket, next) {
return next(new Error('Not Authenticated'));
});
// client.js
var socket = io.connect(window.location.origin);
socket.on('connect', function () {
console.log('socket connected')
});
My problem is I can't capture Not Authenticated error on the client side to handle it and show some popup for example.
Now if Not Authenticated error get executed on server side then socket connection still persists but none of socket.emit('message') don't any work.
How can I capture this error on client side to make some decision?
You should catch error events clientside:
socket.on('error', function(err) {
console.log('The server sent an error', err);
});
2021 update: for Socket.io v3 and up, errors that get passed to middleware callbacks trigger a connect_error event client side, as documented here.

socket.IO can only connect one client (browser) at a time

I am having a problem of using socket IO to connect my server to the client(http website).
On the client, I have a button that when pressed, sends data to the server. However, this only works with one client.
If I have two clients, the first person to open the http website gets the socket IO connection, while the second person can open the page, but can't send any data to the server.
On the client side:
var socket = new io.connect('ServerIP:8090');
socket.on('message', function(obj){
if ('buffer' in obj){
//ignore this
} else message(obj);
});
On server side:
var io = io.listen(server)
, buffer = [];
io.on('connection', function(client)
{
client.send({ buffer: buffer });
client.broadcast.send({ announcement: client.sessionId + ' connected' });
chatGuests.push(client);
client.on('message', function(message){
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.broadcast.send(msg);
});
client.on('disconnect', function(){
client.broadcast.send({ announcement: client.sessionId + ' disconnected' });
});
Instead of using client.broadcast.send(something) and client.send(something) use io.emit('eventName', something). Also, for setting up the server with the variable io use
var socket = require('socket.io');
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var io = socket.listen(server);
And then after your code:
server.listen(8090);
This allows you to use the node.js module express, which allows additional communication between the client and server (but doesn't require you to rewrite your socket.io code).
For your client code, instead of using:
socket.on('message', function(obj){
//Do something
});
Use:
socket.on('eventName', function(something){
//Do something
});
This works for multiple kinds of data passing, not just messages. You can multiple event listeners to each do different things

Socket.io Error (socket.send is not a function)

I'm trying out Websockets/Node.js/Socket.io/Express for the first time and I'm trying to create a simple chat program. Everything runs fine and I see both clients in my node termial.
But when I try to execute my socket.send(), I get an error in Firefox (socket.send is not a function). It doesn't complain about socket.connect() so I know the socket.io.js is loaded.
Here is my server code:
var sys = require('util');
var express = require('express');
var io = require('socket.io');
var app = express.createServer();
app.listen(8080);
app.use(express.static(__dirname));
app.get('/', function (req, res) {
res.render('index.html', {
title: 'Chat'
});
});
var socket = io.listen(app);
socket.on('connection', function (client) {
client.on('message', function (message) {
console.log("Message: " + JSON.stringify(data));
socket.broadcast(message);
});
client.on('disconnect', function () {});
});
My client code:
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
var socket = new io.Socket("http://localhost:8080");
socket.connect();
Then I do some code to get the chat message and send it.
socket.send(JSON.stringify(values));
Explanations
You haven't initialized Socket.io correctly on the server-side and client-side.
Client Side
new io.Socket("http://localhost:8080"); doesn't give you the object that you want, you need new io.connect("http://localhost:8080");.
You need to wait until the client is connected to the server before sending a message.
Server side
socket is the object send back by Socket.IO, you need to use socket.sockets to have access to on.
To broadcast a message, you need to use the client object like this: client.broadcast.send()
The variable data doesn't exist on your broadcast. You probably mean message.
Solution
Server
var sys = require('util'),
express = require('express'),
io = require('socket.io'),
app = express.createServer();
app.listen(8080);
app.use(express.static(__dirname));
app.get('/', function (req, res) {
res.render('index.html', {
title: 'Chat'
});
});
var io = io.listen(app);
io.sockets.on('connection', function (client) {
client.on('message', function (message) {
console.log("Message: " + JSON.stringify(message));
client.broadcast.send(message);
});
client.on('disconnect', function () {});
});
Client
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
<script>
var socket = new io.connect("http://localhost:8080"),
connected = false;
socket.on('connect', function () {
connected = true;
});
// Use this in your chat function.
if (connected) {
socket.send(JSON.stringify(values));
}
</script>
socket.broadcast(message); should be io.sockets.emit('key', message);
when you use the socket object passed in threw the connect event your only emitting information to that client, to emit to all clients you have to use io.sockets.emit().
also with socket.send(JSON.stringify(values)); I think you want to do socket.emit(namespace, data);
see my connection file from one of my projects here: https://github.com/AdminSpot/HangoutCanopy/blob/master/javascripts/connection.js
You have to wait for socket.io to connect on the client side
var socket = new io.Socket("http://localhost:8080");
socket.connect();
socket.on('connect', function() {
socket.emit('event', data);
});

Resources