socket.io emit to default room does not work - socket.io

When I call emit without the io.emit() all the connected clients receive the message as you would expect. However when trying to send a message to the default room using io.to(socket.id).emit(), the client does not receive the message.
Refering to default room documentation at
http://socket.io/docs/rooms-and-namespaces/#default-room
Using nodejs v4.2.6
Client:
var socket = io();
socket.on('connect', function() {
$.ajax({
url: '/some-path',
type: 'POST',
data: {socket_id: socket.id},
success: function(data) {
console.log(data);
}
});
});
Server:
app.post('/some-path', function(req, res) {
var socketID = req.body.socket_id;
io.to(socketID).emit('message', {'message': socketID});
res.end(socketID);
});

This is the correct solution. It was discovered that the default room socket.id being used by the server to set the default room is not the same as the client socket.id. Please advise.
On the client if you evaluate socket.id you get something like, v4eEdSX5RnDSXjzuAAAA
On the server in, io.on('connection', function(socket){}) if you evaluate socket.id you will get something like, /#v4eEdSX5RnDSXjzuAAAA.
Notice the /# prepended to the client socket.id.
So you have two ways of solving this issue
When calling emit prepend /# to the socket ID
Override the io "connection" listener to set the room to the socket ID without the /# prepended
Selected option two is as follows:
io.on('connection', function(socket) {
socketID = socket.client.id;
socket.join(socketID);
console.log('a user connected ' + socketID);
});

Related

Socketio: How can i send a single string over to the client

I am trying to send a string to the client like this:
socket.emit("start", "calm");
but it is throwing an error, is it because it is not an object ?
First thing first, you should make sure your socket between server-side and client-side is connect. And register event and function to the socket.
Server-side
io.sockets.on('connection', function(socket) {
console.log('socket connect' + socket.id);
// when a client connect to server within socket, server will send hello
io.emit('newMsg', "hello")
socket.on('disconnect', function() {
console.log('socket disconnect');
})
// when server receive a message, it will send to all client which connect
to the server
socket.on('data', function (data) {
console.log(socket.id +': ' + data.msg);
var message = {from: socket.id,
msg: data.msg
}
io.emit('newMsg', message)
})
}
Client-side
var socket = io('http://localhost:3000');
socket.on('connect', function (data) {
console.log(data)
})
socket.on('newMsg', function(data) {
console.log(data)
})
// function could bind on button on client side page, get input and send data
function sendData() {
var input = document.getElementsByTagName('input')
var text = input[0].value
var data = { msg: text }
socket.emit('data', data)
}
open console, the information would show in the console. When sending a message on server-side, could use 'broadcast' instead of 'emit' as well to send the message to other clients except you. Read the doc: socket.io doc

Socket.IO client cannot send handshake parameter

Here is my code:
var socket = require('socket.io-client')('http://127.0.0.1:3000/printers', {
query: "shop=" + "123456",
transports: ["websocket"]
});
If I delete query, I can connect to socket. Where am I wrong?
There doesn't seem to be anything wrong with your client-side code. I can connect by copying and pasting your code.
I suspect the problem is within your server-side code. Here is an example I am using with your client-side code:
var http = require('http');
var io = require('socket.io');
var server = http.createServer(function(req,res){
res.writeHead(200);
res.end('Hello, World!\n');
});
server.listen(80);
var socket = io.listen(server);
socket.use(function(socket, next){
console.log("Query: ", socket.handshake.query);
if (socket.handshake.query.shop == '123456') {
next();
}
next(new Error('You cannot use that shop'));
});
socket.on('connection', function(client) {
console.log('New Connection');
});
I'm able to obtain the query data in the 'socket.use' function. If I don't call the next() function, the client will never get the message that the server has received the response and is connected.
I recommend checking out the example used in this thread.

socket.io data from server to client

server.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
app.use(express.static(__dirname + '/public'));
io.on('connection', function(client) {
console.log('Client connected...');
client.on('join', function(data) {
console.log(data);
io.emit('messages', 'Hello');
});
});
index.html
<script>
var socket = io.connect('http://localhost:7777');
socket.on('connect', function(data) {
socket.emit('join', 'Hello World from client');
});
socket.on('messages', function(data) {
alert(data);
});
</script>
I tried to implement very basic of Socket.io.
However, data sending from client to server is available but from server to client doesn't work.
In the command running server.js, 'Hello World from client' is printed. However, alert window doesn't work in the web browser.(I've also tried to console.log).
How to solve this?
Editted
I've put server.js codes in the app.get('/', function(req, res)){ ... }
Then, it doesn't work. Why it doesn't work in app.get?
Try this, I hope it works:
io.on('connection', function(client) {
console.log('Client connected...');
client.on('join', function(data) {
console.log(data);
io.emit('join', data); //this code sending data from server to client
});
});
If you're just trying to fetch some data with an Ajax call such as /test, then there is no need to use socket.io. That's just a classic request/response.
app.get('/test', function(req, res) {
// collect your data and then send it as a response
res.json(data);
});
If you're just trying to incorporate data into a web page that is requested, then you can use res.render() with the template engine of your choice (ejs, handlebars, pug, etc...). That would typically look like this:
app.get('/test', function(req, res) {
// collect your data and then pass it to res.render() to render your
// your template using that data
res.render('someTemplateName', data);
});
The main thing that socket.io is useful for is "pushing" data from server to client without a client request. So, if something happened on the server that the client was not aware of and the server wanted to tell the client about it, then socket.io would be used for that. The classic example is a chat app. Person A sends a chat message to the server that is addressed to Person B. The server receives that message and then needs to "push" it to Person B. That would be perfect for an already connected socket.io connection because the server can just push the data directly to the Person B client, something the server can't do with request/response (since there is no request from person B).
If you still think you need socket.io, then please describe exactly what you're trying to do with it (step by step what you're trying to send to the client).
socket.on("message",function (reply_data) {
console.log('inside on message functions ')
console.log(reply_data);
})
please change 'messages' to "message" that worked for me

User presence in a socket.io 'room'

I have a system where users connect to a 'room' using Socket.io. Right now, when people load a page, the connection is made, and I can see how many people are connected to the given page (the URL dictating the room).
What I want is to be able to see metadata about the users on the page. I want to somehow know that Bob, Steve and Mary are looking at the page. Right now I only get the internal session Ids.
Server
io.on('connection', function(socket) {
socket.on('viewPage', function(data, fn) {
var roomName = 'page-' + data.url;
socket.join(roomName);
var room = io.sockets.adapter.rooms[roomName];
console.log(Object.keys(room).length + ' users connected');
fn({msg: 'Connected to room ' + roomName})
})
});
Client
var socket = io();
socket = io.connect("http://localhost:5000");
socket.on('connect', function(data) {
socket.emit('viewPage', {url: '/foo/bar'}, function(resp) {
console.log(resp)
});
});
From looking at the Socket.io docs there's join and so on, but I don't see any way of attaching metadata to the client connection.
How would I go about doing this? How can I ensure that I can see a list of connected users on a page?
Here's a very simple and unsafe way of passing metadata from the client to the Server and attaching it to the sockets using middleware. Usually only a session id is passed and the data is fetched on the server but I've cut some corners.
//Client
socket = io.connect("http://localhost:5000", {query: 'name=Bob'});
//Server
io.use(function (socket, next){
var name = socket.handshake.query.name;
socket._name = name;
next();
});
Now you can do:
var room = io.sockets.adapter.rooms[roomName];
for (var key in room){
console.log(room[key]._name);
}
Note you should handle multi-tabbing from the same user so you'd need to display only distinct _name values

Socket.io client only joins room on every other connection

I've been trying to make a basic notification system that uses rooms in Socket.io. However, for some reason, it only works every other time you refresh the page.
I've simplified the code to make it easier to debug, but the issue remains. Each time I refresh the page, everything seems to work except joining a room (which only works half the time). What could be going on?
edit: I'm using Socket.io version 1.1.0 and Node.js version 0.10.31
edit2: Added FunnyLookinHat's suggestion (but it still doesn't solve the problem)
Client-Side Code:
socket = io.connect('example.com:8081'),
socket.on('connect', function () {
socket.on('startup', function(data) {
console.log(data.message);
});
socket.emit('joinRoom');
});
Server-Side Code:
var io = require('socket.io').listen(8081);
io.sockets.on('connection', function (socket) {
console.log(socket.id + ' connected!');
socket.emit('startup', { message: 'Socket started!' });
socket.on('joinRoom', function(){
console.log(socket.id + ' joining room lobby'); // prints on every other request
socket.join('lobby');
});
socket.on('disconnect', function() {
console.log(socket.id + ' disconnected!');
});
});
Client Console:
Socket started!
(refreshed page)
Socket started!
Server Console:
UIBqVuOiF1fegMIMAAAB connected!
UIBqVuOiF1fegMIMAAAB joining room lobby
UIBqVuOiF1fegMIMAAAB disconnected!
(refreshed page)
x3nMilBOjjFVjBFJAAAC connected!
(after about a minute once the client window has been closed or refreshed)
x3nMilBOjjFVjBFJAAAC disconnected!
Race condition! Try doing the following in your client code:
socket = io.connect('example.com:8081'),
socket.on('connect', function () {
socket.on('startup', function(data) {
console.log(data.message);
});
socket.emit('joinRoom');
});

Resources