Why doesn't my server respond to an emitted event by the client? I have tried a few trivial examples from the socket.io webpage and they seem to be working fine.
My goal is to emit an event whenever a user focuses out from the input box, compare the input value on the server, and fire an event back to the client.
client-side
$('#userEmail').focusout(function() {
var value = $('#userEmail').val(); // gets email from the input field
console.log(value); // prints to console (it works!)
socket.emit('emailFocusOut', { userEmail: value }); // server doesn't respond to this
});
server-side
io.sockets.on 'emailFocusOut', (data) ->
console.log(data)
Additional info
express 3.0rc4
socket.io 0.9.10
coffee-script 1.3.3
You have to put your custom event inside the io.sockets.on function. The following code will work:
io.sockets.on('connection', function (socket) {
socket.on("emailFocusOut", function(data) {
console.log(data) // results in: { userEmail: 'awesome' }
})
});
If you need some answer from server your server should emit message back to client.
console.log does not do network answer.
var io = require('socket.io').listen(80);
io.sockets.on('connection', function(socket) {
socket.on('emailFocusOut', function(data) {
data.receivedAt = Date.now();
socket.emit('emailFocusOutResponse', data); // answer back
});
});
Then on client you can listen for 'emailFocusOutResponse' and handle this message.
Related
I have a simple implementation, or an attempt at one, of a messaging system just to show an alert of a message to different users. I'm using https://www.npmjs.com/package/vue-socket.io Vue Socket Io but it's just a socket.io. I am attempting to have the client subscribe to an event in mounted. The name is based on their userID. The problem is that my implementation below doesn't work to show the alerts. I can see the event being subscribed to in mount and I can see sending message console log in the server so I know that is getting fired but I don't see the alert being triggered by the emit(Chat_....
server:
io.on('connection', function(socket) {
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
socket.emit(`CHAT_${data.user}`, data.msg)
});
});
client:
On the client, the userIDSelf is a user ID that is passed in as a prop. It's the User's logged in ID and in mounted, they automatically subscribe to the a chat channel with their userid appended to it, like a custom channel.
mounted() {
this.sockets.subscribe(`CHAT_${this.userIDSelf}`, (data) => {
alert(data)
});
},
there is a function sendMessage that takes the values from 2 inputs (not seen) in the template. You have to enter a user ID on who you want the message sent to and then another input with the actual message. These are sent over to the backend server listed above.
methods: {
sendMessage() {
this.$socket.emit('sendMessage', {user: this.userIDReceiver, msg: this.message})
},
}
I see a logical problem here. In your server code
io.on('connection', function(socket) {
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
socket.emit(`CHAT_${data.user}`, data.msg)
});
});
the socket (User 123) which emitted sendMessage event to the server, will eventually also be the socket which will receive the emitted CHAT_456 event from the server. But User 123 socket only listens to CHAT_123 events. The socket is sending itself a message but doesn't receive it.
Possible Solutions
A - the room approach
Once a socket connects on the server, throw it in a room based on it's user id. This requires sending the userid to the server during connection, e.g. with a query parameter. In the client just add a token query parameter to the connection string like
const io = require('socket.io-client');
const socket = io("https://server-domain.com/?token=" + userid);
and through the connecting socket in a room (join) on the server side like
io.on('connection', function(socket) {
const userid = socket.handshake.query.token;
socket.join(userid);
});
then your socket sendMessage would work like this
/* ... server side */
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
io.to(data.user).emit('chatMessage', data.msg);
});
B - the keep reference to the socket approach
Internally every socket has a socket id. Normally these are not exposed the user/clients. However you do have a unique user id. So let's keep a user id / socket instance - relation on the server side, so you can get a reference to the socket object for each corresponding user, using the user id.
The most basic example for it would be a in-memory store on the server side
let socketRefs = {};
io.on('connection', function(socket) {
const userid = socket.handshake.query.token;
socketRefs[userid] = socket;
});
then your socket sendMessage would work like this
/* ... server side */
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
let targetSocket = socketRefs[data.user];
targetSocket.emit('chatMessage', data.msg);
});
I just started on socket.io. I am going through the example mentioned in the web page. Specifically the server code below
io.on('connection', function(socket){
socket.on('nitrous', function(msg){
io.emit('nitrous', msg);
console.log( "Server is emiting the event");
});
});
in conjunction with the client code below
<script src="/socket.io/socket.io.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(e){
e.preventDefault(); // prevents page reloading
socket.emit('nitrous', $('#m').val());
$('#m').val('');
return false;
});
socket.on('nitrous', function(msg){
$('#messages').append($('<li>').text(msg));
console.log( "Client is emiting the event");
});
});
</script>
I understand that we the form is submitted, it would emit an event called 'nitrous' and then the handler registered on the socket would be invoked. But I also noticed that the handler on the socket object at the server too is getting invoked. My first question is how is this happening for all the users who are connected to the application. Secondly, in the server, there is the io.emit() with the same event name which is being passed - how and where is this handled ?. I did not include any io.on() but it still works.
I am referring to this example: https://socket.io/get-started/chat/#Integrating-Socket-IO
Please share your thoughts on the same.
Thanks,
Pavan.
let me rewrite your code to explain what is going on:
// Server
// when server gets new client connected do this:
serverSocket.on('connection', function (client) {
// when server receives event from client that called "nitrous" do this:
client.on('nitrous', function (msg) {
// emit event with name "nitrous" to every client - including sender
serverSocket.emit('nitrous', msg)
// or could just emit event to everyone but sender
// client.broadcast.emit('nitrous') // uncomment this line
console.log('Server receives the event from client')
})
})
Now client side (only javascript):
// Client
$(function () {
const clientSocket = io()
$('form').submit(function (e) {
e.preventDefault() // prevents page reloading
// message that client wants to send
const msg = $('#m').val()
// emit event called "nitrous" to server
clientSocket.emit('nitrous', msg)
// clear input field
$('#m').val('')
return false
});
// when client receives event from server called 'nitrous' do this:
clientSocket.on('nitrous', function (msg) {
// append LI element to list of messages
$('#messages').append($('<li>').text(msg))
console.log('Client receives the event')
})
})
Hope that makes more sense.
I have a problem that i don't seems to be able to solve it. I'm doing some kind of integration with remote system and my code is in iframe but that can't be important for this one i hope :).
I'm trying to send a message from server to specific room/client to begin session. First thing I do is when user log in, I emit message from client side with username.
CLIENT.JS
conn.on('connect', function () {
conn.emit('session', { username: 'some_username' });
}, false);
And on server side i get message and join socket to the room.
SERVER.JS
socket.on('session', function(session) {
socket.join(session.username);
});
I have another module that communicates with this server.js script through redis. So i have two more events in server.js
SERVER.JS
var userCreate = redis.createClient();
userCreate.subscribe("userCreate", "userCreate");
var userDestroy = redis.createClient();
userDestroy.subscribe("userDestroy", "userDestroy");
userCreate.on("message", function(channel, data) {
socket.to(JSON.parse(data).username).emit('beginSession', data);
});
userDestroy.on("message", function(channel, data) {
socket.to(JSON.parse(data).username).emit('endSession', data);
socket.leave(JSON.parse(data).username);
});
But when ever i try to emit message from server to client i broadcast message to everyone. What am I doing wrong?
Well, from the syntax point of view you are doing everything correct.
Didn't you forget to specify the userId property in the endSession?
userDestroy.on("message", function(channel, data) {
socket.to(JSON.parse(data).userId).emit('endSession', data);
socket.leave(JSON.parse(data).userId);
});
If that doesn't work - you should provide the contents of a data object
var io = require('socket.io-client'),
socket = io.connect('targeturl', {
port: 8080
});
socket.on('connect', function () {
console.log("socket connected"); //this is printed.
});
socket.emit('list', {"user":'username',"token": 'mytoken'});
socket.on('message', function(data){
console.log(data);
});
socket.on('error', function(data){
console.log(data); //nothing is printed
});
I see the message 'socket connected' when running this from node.js on the command line but I don't see a response from the 'list' call.
Note that this is a specific question about using socket-io-client from Node.js as a command line application.
I have verified using curl that I can reach the socket server which is REMOTE i.e I do not have the server code but I know that it uses socket.io.
I'm no expert on the matter, but it appears you're attempting to emit the message before the connection is established. (This stuff is asynchronous after all.)
Try moving the emit call inside of the handler for the 'connect' event, to ensure that it happens afterward.
I am trying to proxy emails via NodeJS in order to do very custom processing on outgoing emails on our test server.
This is what I have:
var net = require('net');
var server = net.createServer({allowHalfOpen: true}, function(socket) {
console.log('New connection established.');
socket.setEncoding('utf8');
socket.on('data', function(data) {
console.log(data);
});
socket.on('end', function() {
console.log('Connection closing.');
});
socket.resume();
});
server.listen(25);
It does not yet process the emails, because it simply doesn't even work. I get the connection established message in console every time I send an email, but the data event never gets fired. I'm not sure if it's that the data already came before I bound the event listener, or whether I'm supposed to talk to the client first (HELO?).
I'm trying to access the email contents, basically.