Socket.io question - how does the client and server communicate - javascript

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.

Related

return client socket.io to variable

On the docs page they say that i need to use like this.
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
there is any way to expose the client to a variable?
var socket = io.on('connection');
socket.emit('news', { hello: 'world' });
On the help page they say that Server#onconnection(socket:engine#Socket):Server expose a client, but i can't figure out how to use it. doc
this way i can use socket inside my other functions.
Right now on every function that i emiting stuff i do the io.on('connection', function (socket) all over again
Another question:
There is a way to different files emit event to each other
app.js
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
file1.html emit
<script src="socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost');
socket.emit('event15', function(x){
});
</script>
file2.html receive
<script src="socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost');
socket.on('event15', function(x){
});
</script>
On the server you have to deal with multiple sockets, one for each client. That's why on the server, you write an event handler that sets up the socket for each new client that connects. The basic idea is this:
Server:
io.on('connection', function(socket) {
socket.on('chat message', function(msg) {
io.emit('chat message', msg);
});
});
All of your message handling is supposed to be setup in the outer function. If you want to use the socket elsewhere however, you can pass it on like this:
io.on('connection', function(socket) {
socket.on('login', function(data) {
myServer.attemptLogin(socket, data.user, data.hash);
});
});
The attemptLogin(socket, user, hash) function can now process the parameters, then reply to the client by calling socket.emit()
If you want to store each user's socket in a variable, you need to create a data structure to do that. Here's an example:
var users = {}; // empty object
io.on('connection', function(socket) {
users[socket.id] = socket; // store socket for later use
// ...
});
This is only useful though if a connected user can somehow resume their previous session after a disconnect. Otherwise this is just a question of properly organizing your functions and variables.
As for the second question, you cannot send data from one HTML document to another. As soon as the user clicks a link leading to file2.html, a new socket will be opened and socket.io won't even realize that this is still the same user. As far as socket.io is concerned, some random dude just opened file2.html elsewhere in the world.
There are two ways around this: you can create a single-page app, where the user never actually navigates to another site. However they will still lose the connection if they accidentally close the tab, or navigate back, or refresh the page.
The other way is to use some kind of session information. If the user logs in, you can simply store their username and password hash in localStorage. On each page, check localStorage for the stored credentials, then send a "login" message to the server.

socket.io, server emit event before client set up listener for that event

In the following code snippet(using node.js and socket.io library), sometimes (and sometimes not) server emit event something before client side set up socket listener for something event which will cause that associated anonymous function will not execute.
Client-side: index.html
<script src="socket.io/socket.io.js"></script>
<script>
...
var socket = io.connect('http://localhost:8080/abc');
...
</script>
<script src="/somewhere/test.js"></script>
Content of test.js
...
console.log(new Date().getTime(), 'debugging');
socket.on('something', function(data) {
// will not execute
console.log(data);
});
...
Server-side:
io.of('/abc').on('connection', function(socket) {
console.log(new Date().getTime(), 'EMIT SOMETHING');
io.of('/abc').emit('something', 'b');
});
Result of console.log on the client side: 1439057954676 debugging
Result of console.log on the server side: 1439057954114 EMIT SOMETHING
Why server emit event before client set up listeners in the above example?
Try putting both var socket = io.connect('http://localhost:8080/abc'); and socket.on('something', function(data) in the same script tag.
(Essentially try making your whole script in one HTML element, instead of separating them.)

How to call a function when node server is up?

I want to call a function when the net.serverCreate is up. It need to call this function when the server is started and not when a new connection appears. Event 'listening' dont fire...When I start the server I want to check something in Mysql data-base... How to execute functions when server starts?
My app:
var server = net.createServer(function (socket) {
socket.on('listening', function () {
console.log("Console is listening! "); //Its dont log
});
socket.on('data', function (message) {
});
socket.on('end', function () {
socket.end();
});
});
server.listen(1337,function(){
console.log("Server starts succefully"); //Its working!
});
Event 'listening' dont fire
The callback to createServer is handed a client Socket. Client-side sockets don't listen for requests; they make requests. So a listening event is never emitted by Sockets
On the other hand, net.createServer() returns a server-side socket(similar to Java's ServerSocket)
This should work.
server.listen(1337,function(){
//mysql db query
});
The callback to listen is executed when the server is bound to the specified port, i.e., when the server starts listening. The last parameter to listen is added as a listener for the listening event.
Another way to monitor the server-start event is:
server.on('listening', function() {
//mysql db query
});
Listening event

Socket.io not firing events from client to server

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.

How to be sure that message via socket.io has been received to the client?

How to check that message sent with socket.io library has been received to the client.
Is there special method for it in socket.io?
Thanks for your answers!
You should use the callback parameter while defining the event handler.
A typical implementation would be as follows:
Client side
var socket = io.connect('http://localhost');
socket.emit('set', 'is_it_ok', function (response) {
console.log(response);
});
Server side
io.sockets.on('connection', function (socket) {
socket.on('set', function (status, callback) {
console.log(status);
callback('ok');
});
});
Now check the console on the server side. It should display 'is_it_ok'. Next check console on client side. It should display 'ok'. That's the confirmation message.
Update
A socket.io connection is essentially persistent. The following in-built functions let you take action based on the state of the connection.
socket.on('disconnect', function() {} ); // wait for reconnect
socket.on('reconnect', function() {} ); // connection restored
socket.on('reconnecting', function(nextRetry) {} ); //trying to reconnect
socket.on('reconnect_failed', function() { console.log("Reconnect failed"); });
Using the callback option shown above is effectively a combination of the following two steps:
socket.emit('callback', 'ok') // happens immediately
and on the client side
socket.on('callback', function(data) {
console.log(data);
});
So you don't need to use a timer. The callback runs immediately except if the connection has any of the following states - 'disconnect', 'reconnecting', 'reconnect_failed'.
You can use the socket.io's acknowledgements.
Quote from the socket.io documentation:
Sometimes, you might want to get a callback when the client confirmed
the message reception.
To do this, simply pass a function as the last parameter of .send or
.emit. What's more, when you use .emit, the acknowledgement is
done by you, which means you can also pass data along.
On the client side simply emit the event with your data, the function will be called whenever the server responds to your event:
client.emit("someEvent", {property:value}, function (data) {
if (data.error)
console.log('Something went wrong on the server');
if (data.ok)
console.log('Event was processed successfully');
});
On the server side you get called with the data and the callback handle to send the response:
socket.on('someEvent', function (data, callback) {
// do some work with the data
if (err) {
callback({error:'someErrorCode', msg:'Some message'});
return;
}
callback({ok:true});
});
When you add a function as the last parameter of .send() or .emit() method calls, this function is called when the other party receives the message.
socket.send('hi', function() {
// if we are here, our salutation has been received by the other party.
});

Categories

Resources