Socket.io 1.0 Middleware join room not working properly - node.js

I tried to add new socket to some rooms in a middleware, but it seems not working while a first emit haven't be done for a socket(client side). When a socket (client side) send a 'message' event it will then work and be part of the room.
Is it a normal behavior?
Am I mandatory to join room in 'connection' event?
app.js (server side)
var app = require('http').createServer(function (req, res){
res.end('no rest');
});
var io = require('socket.io')(app);
app.listen(7076);
io.use(function(socket, next){
socket.join('toto');
next();
});
io.on('connection', function (socket) {
socket.on('message', function (data) {
socket.to('toto').emit('message', data);
});
});

According to the documentation, socket.to('toto').emit... syntax is not correct. You should use one of the following forms:
send everyone in "toto" room:
io.to('toto').emit('message', data);
send everyone in "toto" room except the sender:
socket.broadcast.to('toto').emit('message', data);

In fact the problem wasn't on the server side at all... It was my client that i didn't describe.
When clicked on a button to send a message here is the function called
function messageManagement(cb)
{
var message = $('#message_text').val();
if (!message || message.length == 0)
message = 'I am watching you';
socketClient.emit('message', {message:message});
socketClient.on('message', function (data){
console.log(data.messsage);
drawMessage(data);
});
}
As you can see each time the client emit a message it also register to the response event. So each time I emit a message a registered one more time to same event... It was messy so i changed this and it worked..

Related

how to send typing alert and message to users in a particular room using nodejs socket.io

The code below works fine by broadcasting typing notification and chat messages to all connected users.
Here is what I want: How do I send typing notification and chat messages only to users connected to a particular room
say Room1, Room2 etc.
here is the code
index.html
var socket = io();
var user = 'nancy';
function submitfunction(){
var from = 'nancy';
var message = 'hello Nancy';
socket.emit('chatMessage', from, message);
}
function notifyTyping() {
var user = 'nancy'
socket.emit('notifyUser', user);
}
socket.on('chatMessage', function(from, msg){
//sent message goes here
});
socket.on('notifyUser', function(user){
$('#notifyUser').text(nancy is typing ...');
setTimeout(function(){ $('#notifyUser').text(''); }, 10000);
});
server.js
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('chatMessage', function(from, msg){
io.emit('chatMessage', from, msg);
});
socket.on('notifyUser', function(user){
io.emit('notifyUser', user);
});
});
am using npm installed socket.io ^2.3.0
To send the message to a specific room, you will have to create and join a room with roomId. Below is a basic code snippet
//client side
const socket = io.connect();
socket.emit('create', 'room1');
// server side code
socket.on('create', function(room1) {
socket.join(room1);
});
To emit data to a specific room
// sending to all clients in 'room1'except sender
socket.to('room1').emit('event',data);
// sending to all clients in 'room1' room, including sender
io.in('room1').emit('event', 'data');
You can follow this question for details on how to create a room?
Creating Rooms in Socket.io
This emit cheat sheet might also be useful:
https://github.com/socketio/socket.io/blob/master/docs/emit.md

Socket.io, Node, Corodva, I don't recive message in client receptor

I have a problem when I try send message from a client emisor with "emit" and I try catch the message with "on" in a client receptor.
I don't know what is the problem, my code is this:
Emisor Client:
socket.emit("callDriver", data);
Receptor Client:
socket.on("sendToDriver", function(data){
console.log(data);
})
Server:
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
socket.emit('sendToDriver', data);
})
})
Thanks community
Guys I resolved the problem, it's strange in the official documentation of Socket.io they say that when you send data in a .emit you should send this with "socket.emit()" (server side) but I try change socket for io and with this mode work it.
In conclusion:
// I changed this:
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
socket.emit('sendToDriver', data);
})
})
// for this:
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
io.emit('sendToDriver', data);
})
})
Thanks guys!
Here is a simple rooms solution for you. The init() part is very low-tech/simple but you did not say how you intend to populate the socket server with the client userId/session-data when you connect to the server for the first time.
//Client
socket.on('connect',()=>{
socket.on('init',()=>{
socket.emit('init', 'userid')
})
})
socket.on("sendToDriver", function(message){
console.log(message);
})
sendMessage(message){
let data = {userId: "userId", message: message}
socket.emit("callDriver", data);
}
//Server
var io = require('socket.io')(server);
//Triggered by each client separately.
io.on('connection', function(socket){
socket.on('init', (driverId)=>{
//When your web socket starts for the first time, each user creates their own room with their main userId that is used in your mobile app.
//Your setup is so basic, that the server('connection') -> server.emit('init') -> client.on('init') -> client.emit('init') flow is the most sane example for now.
//However this init() setup is primitive -- you need an authentication flow and to pass up the userId/session data with a socket.io 'middleware' function or the 'socket.io-auth' library (recommended)
socket.join(driverId)
})
socket.emit('init')
//Data sent to callDriver will contain the userId of the desired receipient. Since this user is already waiting in that room for us, we join it,
//send the message, and then leave immediately.
socket.on('callDriver', function(data){
socket.join(data.driverIdToCall)
socket.to(data.driverIdToCall).emit('sendToDriver', data.message);
socket.leave(data.driverIdToCall)
})
})

Expose socket.io listeners after client action

Is there a way to set up socket.io listeners for certain clients after they execute a command? For example:
socket.on('setupServer', function (data) {
console.log("setupServer called");
// Now set up listeners
socket.on('serverAction', function (data) {
console.log('Listener for clients calling setupServer');
});
});
In the above, a client has connected and has issued a 'setupServer' command to the node.js server. The server now listens for 'serverAction' from the specific client. Other clients won't be able to use 'serverAction' without calling 'setupServer' first.
You could create a room and validate some data from user and then join those users to that room, after that emit some events to that users in that room.
Something like this.
server.js
var io = require('socket.io')(server);
io.on('connection',function(socket){
socket.emit('auth_user')
socket.on('response_from_user',function(data){
if(data.name === "Blashadow"){
//join that user to the room
socket.join('/room',function(){
//emit some custom event to users in that room
io.in('/room').emit('custom_event_room', { info: 'new used connected from room' });
});
}
});
});
client.html
var socket = io('localhost');
socket.on('auth_user', function (data) {
socket.emit('response_from_user', { name : "Blashadow" });
});
socket.on('custom_event_room',function(data){
console.log(data);
});

Socket.io : How do I handle all incoming messages on the server?

I want to be able to handle all messages that are coming in from clients in a single handler.
Example client code:
var socket = io.connect('http://localhost');
socket.emit('news', { hello: 'test' });
socket.emit('chat', { hello: 'test' });
Example server code:
io.sockets.on('connection', function (socket) {
socket.on('message', function (data) {
console.log(data);
}); });
I'd like to be able to log every message even if its sent on news, chat or whatever other name using emit. Is this possible?
Note: The above server code does not work. There is nothing currently logged. I am just wondering if there is a single event which could be handled for all messages for every emit name.
That is possible by overriding socket.$emit function
//Original func
var x = socket.$emit;
socket.$emit = function(){
var event = arguments[0];
var feed = arguments[1];
//Log
console.log(event + ":" + feed);
//To pass listener
x.apply(this, Array.prototype.slice.call(arguments));
};
It's even easier on Socket.Io >3 using the socket.onAny(listener):
this.socket.onAny(m => {
..
});
This is supported out of the box now as of Socket-io 2.0.4, you simply need to register a middle ware (source from socketio-wildcard):
As of Socket.io v2.0.4 (commit), you can use a socket middleware to
catch every incoming Packet, which satisfies most of
socketio-wildcard's use cases.
io.on('connection', (socket) => {
socket.use((packet, next) => {
// Handler
next();
});
});
This is an open issue with Socket.IO.
At this time, if you really need it, you will probably have to fork Socket.IO. See 3rd-Edens comment for how to do it.

socket.io implementing a simple chat

I tried to ask this on the socket.io google group but no one could (or didn't wanted to) help me.
I have this piece of code on the server side:
var chat = io
.of('/chat')
.on('connection', function (socket) {
socket.emit('message', {
that: 'only'
, '/chat': 'will get'
});
});
chat.on("message", function(data){
console.log(data);
});
While on the client side I have this code:
var chat = io.connect('http://localhost/chat');
chat.on('message', function (data) {
chat.emit('hi!');
});
chat.emit("message", {"this": "is a message"});
On the console I can see that the first message from the server is sent but it seems like the client, once connected and received the message, doesn't emit the 'hi!' message. Moreover I want the client to emit also another message, namely the last line I pasted. Also this message is not received by the server (which in theory should log it).
I'm surely doing something wrong, can anyone point out where exactly this is happening?
What I want to achieve in the end is just setting up a simple chat-like system, but I want this stuff (the channels) working before actually writing the chat itself. Thanks
The reason why that it doesn't the "hi" is not sent is because the first argument in .emit is the event name, in which in here, it is "hi". Technically if you do the following on the server side, I think you should get an undefined data(since you didn't put anything as the second argument which is the object to be sent):
.on('hi',function(data){
console.log(data) // should log "undefined"
});
You can also use .send which is like the web-sockets semantics, and sends to the the message event. If you change the .emit to .send in the client side, it should work.
In summary:
.emit('eventName', 'data') // sends to the eventName name
.send('data') // sends to message event
Working client side code:
var chat = io.connect('http://localhost/chat');
chat.on('message', function (data) {
chat.send('hi!');
});
chat.emit("message", {"this": "is a message"});
I dumbed it down a little bit, but:
Server:
var io = require('socket.io').listen(8080);
var chat = io
.of('/chat')
.on('connection', function (socket) {
socket.send('welcome to the interwebs');
socket.on('message', function(data) {
console.log(data);
});
});
Client:
<html>
<body>
<script src="http://10.120.28.201:8080/socket.io/socket.io.js"></script>
<script type="text/javascript">
var chat = io.connect('http://10.120.28.201:8080/chat');
chat.on('connect', function () {
console.log("connected");
chat.send('hi!');
chat.on('message', function (data) {
console.log(data);
});
});
</script>
</body>
</html>

Resources