Can't send a message from server to client with socket.io - socket.io

I'm new to socket.io and was trying to send a message from server to client while following the instructions of basic emit on https://socket.io/docs/v4/emitting-events/. I expected when I connected to the socket, I would have the word 'world' printed on the console but I failed without knowing why. Did I do something wrong?
Server
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
io.emit('welcome', 'world');
});
http.listen(port, () => {
console.log(`Socket.IO server running at http://localhost:${port}/`);
});
Client
var socket = io();
socket.on('welcome', (arg) => {
console.log(arg);
}

After io.on('connection') You have to receive message from client using
socket.on('welcome',(data) {
//from there emit to client receive message
}) ;

Related

socket.io client not able to connect and receive messages emit by server

I am emitting messages from socket.io server running on port 8001
but my socket.io client not able to connect and receive these messages
my index.html (client):
<script src="https://cdn.socket.io/socket.io-4.0.0.js"></script>
<script>
//var socket = io();
//var socket = io.connect('http://localhost:8001');
var socket = io('http://localhost:8001', { transports : ['websocket'] });
socket.on('connect', function(){
console.log("connected");
socket.on("message", data => {
console.log(data);
});
});
</script>
My nodejs server code:
const app = require("express")();
const server = require("http").createServer(app);
const io = require("socket.io")(server, {
cors: {
origin: '*',
}
});
io.on("connection", () => {
console.log("Connected!");
});
var redis = require('redis');
//var url = "redis://:#localhost:6379";
//var redis = require('redis-url').connect();
//var client = redis.createClient(url);
var client = redis.createClient();
//var client = redis.createClient();
client.on("error", function(error) {
console.error(error);
});
client.subscribe('notification');
client.on('message', function(channel, msg) {
console.log("Message received: "+msg);
io.sockets.emit(msg);
});
console.log('starting server on 8001...');
server.listen(8001);
My node js server console logs:
starting server on 8001...
Message received: from laravel
io.sockets.send(msg);
this worked for me. also make sure you are using the same version of socket.io on both client and server

HapiJS and Socket IO not emit

I'm trying to setup socket.io with hapi. I've setup a barebones repo here: https://github.com/imcodingideas/socketio-hapi-example but this is the gist of it. On the server.js I am listening for a connection
io.sockets.on('connection', (socket) => {
socket.emit({ msg: 'welcome' })
})
and on the client I'm sending a connection
socket.on('msg', data => {
console.log(data)
socket.emit('my other event', { my: 'data' })
})
I'm not getting any cors errors or nothing so it's able to connect.
Your code does work and it doesn't matter where you put the server.start().
The problem is your client side code. The event socket.on('connection') does not exist for the socket.io client. The event is called connect.
IO - Event: ‘connect’ Documentation
The following code snippet should work.
const socket = io('http://localhost:8081');
socket.on('connect', data => {
console.log('connected');
});
socket.on('msg', data => {
console.log(data);
});
setTimeout(() => {
socket.emit('another event', 'another events data')
}, 2000)
server:
const init = async () => {
const io = SocketIO.listen(server.listener)
io.sockets.on('connection', (socket) => {
socket.emit('msg', 'welcome')
socket.on('another event', (data) => {
console.log(data);
})
})
await server.start()
console.log(`Server running at: ${server.info.uri}`)
}
Do not start the server before you initialize the Socket Listener.
'use strict'
const Hapi = require('hapi')
const SocketIO = require('socket.io')
const server = Hapi.server({
port: 8081,
host: 'localhost'
})
const init = async () => {
// await server.start() // not here
const io = SocketIO.listen(server.listener)
io.sockets.on('connection', (socket) => {
socket.emit('msg', 'welcome')
})
await server.start() // but start it here.
console.log(`Server running at: ${server.info.uri}`)
}
init()
Pro tip
You can use Firecamp to test socket events and listeners visually

Can't use Express to send data back to client more than once

In my app, I send a post request to the server with data containing a CSV file:
$.ajax({
type:"POST",
contentType: "application/json",
url:"/",
data: JSON.stringify({fileData:My_CSV_FILE}),
success: function(csvJson) {
console.log('in the done block!');
//can use csvJson in this handler
});
});
Note: I'm posting to the home route, and I am able to get a response with the data converted from the server. The problem is that whether I run on localhost or Heroku, I am only able to trigger the POST request once, then I have to restart the server (even if I refresh the page). So I know the issue is with my route somewhere:
UPDATED TO INCLUDE FULL SERVER FILE:
'use strict';
const express = require('express');
const csvtojson = require('csvtojson');
const PORT = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const Converter = require('csvtojson').Converter;
var converter = new Converter({});
let app = express();
app.use(bodyParser.json({limit: '300kb'}));
app.use(express.static(__dirname +'/public'));
app.post('/',function(req,res) {
var csvFile = (req.body.fileData);
converter.fromString(csvFile, function(err, result) {
if(!err) {
console.log(result);
res.json(result);
}else {
res.json({error: 'Could not convert'});
}
})
});
app.listen(PORT, () => {
console.log(`app listening on port ${PORT}`);
});
I'm using Express 4. Again, everything works, but only once. When I run Heroku logs, or check the console on localhost I get:
Error: Can't set headers after they are sent.
But I don't understand how I'm re-setting them.
If wanting to run on localhost, here is a link to the projects github: https://github.com/qctimes/calendar_export
You should move the converter instantiation to be done inside the app.post callback method. This way it will instantiate a new object at every request.
This is is how your code should be:
'use strict';
const express = require('express');
const csvtojson = require('csvtojson');
const PORT = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const Converter = require('csvtojson').Converter;
let app = express();
app.use(bodyParser.json({limit: '300kb'}));
app.use(express.static(__dirname +'/public'));
app.post('/',function(req,res) {
var csvFile = (req.body.fileData);
var converter = new Converter({}); // instantiation is done here
converter.fromString(csvFile, function(err, result) {
if(!err) {
console.log(result);
res.send(result);
}else {
res.send({error: 'Could not convert'});
}
});
});
app.listen(PORT, () => {
console.log(`app listening on port ${PORT}`);
});

Socket.io namespace connection confuse

All:
I am pretty new to socket.io, when I tried namespace, I wonder why both the default channel and specified channel get called like:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
console.log("Send chat page");
res.sendFile(__dirname+'/index.html');
});
io.on('connection', function(socket){
console.log("Connected");
});
var chat = io.of("/chat");
chat.on('connection', function(socket){
console.log("Connected chat");
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
And the client code is like:
var socket = io("http://localhost:3000/chat");
When I run it, the console print out both "Connected" and "Connected chat"
I wonder why it works like this and how to only connect to chat channel?
Thanks

Difference between io.on and socket.on in Socket.io?

I am confused on what the 'socket' parameter is that is passed with the function (In 'The enigma' section). Then the parameter gets used 'socket.on'. What is the difference between io.on and socket.on?
The following code is slightly adapted from the Socket.io chat application example.
Variables
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app)
var io = require('socket.io').listen(server);
The enigma
io.on('connection', function (socket) {
console.log('user connected');
socket.on('message', function(msg) {
console.log('message: ' + msg);
io.emit('message', msg);
})
});
Start server
server.listen(3000, function() {
console.log('server is running');
});
index.jade
body
script(src="/socket.io/socket.io.js")
form(method='post', action="/")
input(type='text', id='user', autocomplete='off')
input(type='submit', onClick="myFunc()")
strong messages:
p(id="messages")
script.
var socket = io();
socket.on('message', function(msg) {
console.log('client: ' + msg);
});
function myFunc() {
var text = document.getElementById('user');
socket.emit('message', text.value);
text.value = '';
};
In your code example, io is a Socket.IO server instance attached to an instance of http.Server listening for incoming events.
The socket argument of the connection event listener callback function is an object that represents an incoming socket connection from a client.
Both of them can listen for events with the on method.
It might help you visually understand how the two are separate if you re-imagine your code sample like this:
var connectionEvent = function(socket) {
console.log('user connected');
socket.on('message', function(msg) {
console.log('message: ' + msg);
io.emit('message', msg);
});
};
io.on('connection', connectionEvent);

Resources