I am just starting to try out node.js and its very likely that I am mistaken so please bear with me :)
From what I understand, the emit function sends out a custom event and on picks up events and then does something.
Here is of bit of the code from the book I'm learning from.
socket.on('rooms', function(rooms) {
console.log("room received");
$('#room-list').empty();
for(var room in rooms) {
room = room.substring(1, room.length);
if (room != '') {
$('#room-list').append(divEscapedContentElement(room));
}
}
$('#room-list div').click(function() {
chatApp.processCommand('/join ' + $(this).text());
$('#send-message').focus();
});
});
setInterval(function() {
socket.emit('rooms');
console.log("room emitted");
}, 1000);
It is logging "room emitted" in the console every second however, it isn't logging "room received"
This shows that it should be emitting the rooms event and the on function should be picking it up. However for some reason it isn't.
Is there something I'm doing wrong???
socket.emit() sends information from the server to the client(s).
socket.on() receives information sent from the clients to the server.
You can't emit a message from the server to the server unless the server is connected as a client to itself.
Hopefully this was helpful.
Related
I'm a starter developer. I use socket.io for my app, which is based on a chat app.
I have a problem when the client disconnects accidentally (E.g. wi-fi on the PC disconnects). When wi-fi is connected again, the client enters the 'reconnect' event. After that, the connection is correctly reseted in the upper way (client to server) but won't work in the down way (server to client). After the re-connect my client will emit events that run on the server... but the server can't emit events that work on the client (the one that reconnected).
E.G:
client side:
I have this button created when the user logs in that when clicked sends the 'ready' event to the server.
socket.on('login', function (data) {
connected = true;
$matchId=data.id
var btn;
btn = document.createElement("BUTTON");
btn.innerHTML= "Ready";
btn.className = "readybtn";
btn.id = "readyBtn";
btn.onclick = function ready(){
socket.emit('ready',{
id: $matchId
});
};
document.getElementById("dropdownDiv").appendChild(btn);
});
server side (extract of one of the multiple events i've designed).
io.on('connection', function (socket) {
socket.on('ready', function(data){
var matchIdx;
for (var i = 0; i < srv.matches.length; i++) {
if(srv.matches[i].matchId == data.id) matchIdx = i;//indexOf
}
socket.to(srv.matches[matchIdx].matchId).emit('new message',{
username:socket.username,
message: "I'm ready"
});
}
});
Therefore, as you can see the when some client clicks on the Ready button, a I'm ready message with the client's username appears to everybody in the room.
My problem comes here, after the reconnect event (from socket.io) if I test this, the message will be displayed on all the clients except for those that reconnected. Even if I switch off the wi-fi on a client and then click on the ready button, I will see the I'm Ready message in all the clients but the one that reconnected. This means, that after the reconnect, the client is able to trigger the 'ready' event of the server, but the server cannot establish the connection to the client, since the 'new message' event is not triggered in the reconnected client.
I've tried to emit directly to the client that reconnected, to check if it is related to the rooms, but it does not work either.
Can somebody tell me how to solve this? Refreshing is not an option..
Thanks in advance.
I attach the reconnect event:
socket.on('reconnect', function () {
log("you were reconnected");
});
PS: Sorry for poor English and explanation, it is my first question.
I am trying to set up a webrtc app. For now, it connects two people when they click connect. But if I have multiple connections open, and then when one of the people from the very first connection clicks disconnect, it literally disconnects EVERYONE who has a connection. I tried this with 3 connections, and disconnected the 2nd connection, and that only makes the 3rd connection disconnect, while the first is still connected.
So basically, it's a downward spiral. If a connection disconnects, then all connections created AFTER that one connection also get to disconnect. But all connections before that connection are still active.
I think it has something to do with the socket.io code, because in the console.log I am receiving the message from socket.io as someone in a totally different connection disconnects. Server code:
socket.on("sessiondesc", function(sessiondesc)
{
if (sessiondesc == true || sessiondesc.type === 'answer')
{
//the random room is generated before the socket.on sessiondesc thing.
socket.join(room)
}
socket.in(room).emit("sessiondesc", sessiondesc);
});
socket.on("quit", function(quit)
{
socket.leave(room)
});
This is client code:
socket.on("sessiondesc", function(sessiondesc)
{
//stuff I do here with webrtc... like create offer, answer, and such.
else if (sessiondesc == false)
{
pc.close();
pc = null;
console.log("GOT THE FALSE SESSION DESC! GOT IT");
quit = true;
socket.emit("quit", quit);
}
document.getElementById("disconnect").addEventListener("click", function(e)
{
console.log("The person clicked disconnect!");
quit = true;
sessiondesc = false;
socket.emit("sessiondesc", sessiondesc);
socket.emit("quit", quit);
pc.close();
pc = null;
});
So basically on all the other connections that disconnect, I can see the console.log("GOT THE SESSION DESC") thing... And I'm thinking like, why are these other rooms getting this sessiondesc? They shouldn't be, I'm only emitting it to a specific room!
I'm new to node.js and I'm making a simple chat app to get started. I'm a bit confused with the socket.set and socket.get methods.
The way the app works, is - first the client sets its username (pseudo):
function setPseudo() {
if ($("#pseudoInput").val() != "")
{
socket.emit('setPseudo', $("#pseudoInput").val());
$('#chatControls').show();
$('#pseudoInput').hide();
$('#pseudoSet').hide();
}
}
On the server, the pseudo is fetched with:
socket.on('setPseudo', function (data) {
socket.set('pseudo', data);
});
If I understand correctly, the server sets the pseudo variable with data received from this particular client. The server can later get that variable with socket.get. The following code broadcasts a message from a client to all clients:
socket.on('message', function (message) {
socket.get('pseudo', function (error, name) {
var data = { 'message' : message, pseudo : name };
socket.broadcast.emit('message', data);
console.log("user " + name + " send this : " + message);
})
});
What I don't understand is, why can't the client itself use socket.get to fetch its own pseudo? Using socket.get('pseudo') gives an error saying socket.get is not a function. Or am I overcomplicating this, and it would be better to just store the pseudo in a hidden field on the client or something similar? It just feels strange that a client should have to get its own username from the server.
EDIT:
Upon clicking Send, this code displays the sent message on the client itself. However, the displayed username is "Me". How can I modify it to show the client's username from the server?
addMessage($('#messageInput').val(), "Me", new Date().toISOString(), true);
function addMessage(msg, pseudo) {
$("#chatEntries").append('<div class="message"><p>' + pseudo + ' : ' + msg + '</p></div>');
}
You have to realize that although socket is a name used by both the server and the client, and interfaces are similar these are two independent things. (i.e. server socket and client socket) describing two ends of one connection.
If server sets some data on a socket what it actually does is it saves some data in its own memory and remembers that this data is associated with the socket. So how would client read something from server's memory? How can machine A read data from machine's B memory? Well, the only (reasonable) possibility is to send that data over network and this is actually what happens.
As for the other question: it's actually natural for the client to get its own name from the server or at least validate that name. Consider this scenario: two clients connect to the server and use the same name. This would lead to a conflict so it is up to the server to solve the problem. Basically you would tell one of the clients "sorry, this name is already being used, use something else".
I'm trying to build a simple chat client and am having some issues getting it working across multiple clients. Chances are I've missed something really simple. When I send something from one client it is logged in that client but not in any others.
Server:
var io = require('socket.io').listen(5000);
io.sockets.on('connection', function (socket) {
socket.on('send', function (data) {
socket.emit('receive', data);
});
});
Client:
var socket = io.connect('http://localhost:5000');
socket.on('receive', function(data){
console.log("Data received at " + new Date() + ": " + data);
});
The socket variable that gets passed to your callback function is a handle on the client that connected, so socket.emit is behaving correctly, i.e. it should only send to the client that originated it.
Try:
socket.broadcast.emit('receive', data);
to send to everybody except the originating client, or
io.sockets.emit('receive', data);
to send to all clients including the originator.
You want to emit on all sockets, not just the one that sent the message.
So you should be using:
io.sockets.emit('recieve', data);
This is assuming that you aren't logging the data on the sending client before sending it to the server. In that case you'll want to use:
socket.broadcast.emit('recieve', data);
Which will send the message to all connected clients except the sender.
See here for reference on Socket.io
Edit: Trevor beat me to it. However, for some additional clarification: io.sockets is the same as io.of(''). Which is handy to know for when you start using namespaces in a scoket.io app.
Normally, when I send some JSON from one client to another, it works fine. But if there is only one client, it still sends packets. My solution was to (on the server-side, in node.js):
var clients = io.sockets.clients();
if(clients.length > 1){
// send stuff to other client
}
But when I do that, something extraordinarily strange occurs. I'll open up a client, start instigating the actions during the if statement, and the console, which prints the JSON before sending it, does nothing, because there is only one client. When I open up another client and instigate the actions during the if statement, the console will print out the JSON and send it to my other client. However, if I go over to my first client that I opened and instigate the actions in the if statement, the console won't print anything out, and it won't send anything. Why? I tried changing the if statement to say:
if("hello" === "hello"){
// do the same stuff as before
}
and both clients could send JSON to one another, but because I had changed the if statement, with one client open I would still send useless packets. For obvious reasons, the optimal situation would be if it wouldn't send packets with one client, but would send packets properly with more than one.
I hope that was clear, I'm sorry if that wasn't.
If I need to, I'll post more code.
EDIT:
Here is the code that updates the array:
var clients = io.sockets.clients();
io.sockets.on("connection", function (socket) {
clients.length++;
socket.on("disconnect", function() {
clients.length--;
console.log(clients.length + " clients are connected");
});
console.log(clients.length + " clients are connected");
});
Haven't done any note.js lately, maybe this is bogus. But I thought: maybe the clients variable is defined for each client when he connects, and not updated later on. This seems the logic thing to me. I think that what you need to do is: fire an event to all clients when a new client connects, and update the "clients" variable.
I'm not sure how your code works (what's this: clients.length++ ?? Incrementation of array's length??) but try doing this the "normal" way:
var clients;
io.sockets.on("connection", function (socket) {
clients = io.sockets.clients();
socket.on("disconnect", function() {
clients = io.sockets.clients();
console.log(clients.length + " clients are connected");
});
console.log(clients.length + " clients are connected");
});
or even better (without holding global reference to connected users):
function get_clients() {
var clients = io.sockets.clients();
console.log(clients.length + " clients are connected");
}
io.sockets.on("connection", function (socket) {
socket.on("disconnect", function() {
get_clients();
});
get_clients();
});
Because io.sockets.clients() returns the array of all connected clients at the moment of calling it (perhaps that's why you get this strange behaviour).