I have html page sent by node.js server and socket.io component that connects to that server like this:
var socket = io();
Also several socket events:
socket.on('server-message', function(type, content) {
...
});
socket.on('server-update', function(type, content) {
...
});
The problem is that in the moment server is stopped, i get client side errors:
https://example.com/socket.io/?EIO=3&transport=polling&t=LptmQyC net::ERR_CONNECTION_REFUSED
Once server is started again it crashes in a 30 seconds after.
It looks like i could use a detection if server is not available anymore and just destroy all socket related events, then reconnect by page refresh or some button.
Maybe someone could help me with this.
I dont believe that much can be done about the error, its internal socket.io error that is a result of unsuccessful server polling.
For better understanding, once connection is severed, socket.io goes into ajax polling and will try to reconnect as soon as possible (meaning as soon as server is up again).
Server crash after reconnect on the other hand can be addressed very easy. The code you presented is only functional in terms of how to connect, you are missing handlers for disconnect and optionally - reconnect.
I will show you how you can add to this code to manage disconnects (and prevent server crashes after bringing it back up).
First of all connect to server:
var socket = io();
Create a disconnect event right after (btw its also a code for server side disconnect event):
socket.on('disconnect', function() {
destroy_socket_events();
});
Create function that will destroy all your listeners:
var destroy_socket_events = function() {
socket.off('disconnect');
socket.off('server-message');
socket.off('server-update');
// add all other socket events that you have in here ...
};
Now what is going to happen is this:
connection is made
server is stopped
client triggers disconnect event
function destroys all of your socket listeners
server is back up
client reconnects (socket.io will do it because of the polling)
no listener is ever triggered at that point
So you can safely reinitialize all of your code and attach listeners again properly.
Related
So, I am still in the experimental phase of Socket.io, but I just can't figure out why my code is doing this. So, I have the code below and when I console.log the code, it repeats the the connection even when there is only one connection. Do you know a solution?
io.on('connnection', (socket) => {
console.log("A new user is connected.")
})
Client side:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io()
</script>
Node.js Console:
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
...
(Note: there is only one connection, and I have already cleared the browser cashe)
Here are some of the possible reasons for socket.io connecting over and over:
Your socket.io client and server versions do not match and this causes a connection failure and an immediate retry.
You are running with some infrastructure (like a proxy or load balancer) that is not configured properly to allow lasting webSocket connections.
You are running a clustered server without sticky webSocket connections.
You have put the server-side io.on('connnection', ...) code inside some other function that is called more than once causing you to register multiple event handlers for the same event so you think you're getting multiple events, but actually you just have multiple listeners for the one occurrence of the event.
Your client code is calling its var socket = io() more than once.
Your client page is reloading (and thus restarting the connection on each reload) either because of a form post or for some other reason.
FYI, you can sometimes learn something useful by installing listeners for all the possible error-related events on both client and server connections and then logging which ones occur and any parameters that they offer. You can see all the client-related error events you can listen to and log here.
To solve repetion problem write your code like that for socket:
io.off("connnection").on('connnection', (socket) => {
console.log("A new user is connected.")
})
I ran into a weird problem when using socket io after many years.
Years ago, I could use the following code on client side
socket.emit('user', {userId: 2});
// and somewhere else in the code id listen for incoming 'user' replies
socket.on('user',(reply) => {
// do something with user data received from server
});
Now, when I have the same code on the client side, and I emit "user" request, the socket.on('user') callback is immediately fired with request payload which was supposed to go to the server( which is offline ).
I thought socket.on() listeners were triggered only by replies from the server and not by the outgoing messages from the client itself.
Is the socket.io supposed to work like this or am i missing something in configuration?
I think I solved this by accidentally stumbling on another post about how socket.io keeps the connection alive.
The socket.emit('user', {userId: 2}); was an example.
In my real app, I used the event name "ping" which seems to be reserved by socket.io.
The client keeps pinging and listening to pings constantly.
So, when I added my own socket.on('ping') listener, it hooked into socket.io internal ping/pong system. ( at least i think thats the case )
I have the following code on my client side:
btn.addEventListener('click', function(){
socket.emit('chat',{
message: message.value,
handle: handle.value
});
});
So I think I understand the above. When a click event happens, run the callback function. Inside the callback function, have socket emit this "chat" event to the server. Along with the event socket emits, pass the JSON data.
Now on the server side we have this:
var io = socket(server);
io.on('connection', function(socket){
socket.on('chat', function(data){
io.emit('chat', data);
});
});
I think I understand this as well. Bind the socket to this server. Then listen to the connection event. When that event is invoked, socket.io (will magically?) pass a socket object to our function. We then listen to all of our sockets for a chat. As defined on the client side, take the data emited from the chat and emit it back to all of our sockets.
socket.on('chat', function(data){
// do cool stuff
})
Again in the above example, we have the client listening to the event on the server side.
My question is, how does the event get "passed" to the client side? Is this some sort of native Javascript functionality? I would like to know more of what happens on the backend.
The event gets passed to the server through websockets. Its a tcp connection from the browser to the server. The connection is full duplex meaning the server can send real time data to the client and vise versa.
In your frontend code you should have something that looks similar to
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
This code asks the server for a tcp connection using web sockets. Once the browser is connected to the server through websockets, socket.io can send events to the send through the connection.
The socket that is passed in the connection event is just a reference to whatever socket gets created when the frontend connects. The socket gets a unique id and with this reference you can communicate in real time to the web browser client.
If you want a deep dive into web sockets, I'd recommend reading this
https://www.rfc-editor.org/rfc/rfc6455
This question already has an answer here:
How can I let the javascript catch a signal from node and prompt a window right after that?
(1 answer)
Closed 5 years ago.
I noticed if I want to emit a message like
io.on('connection', function(socket){
socket.emit('signal')
})
Somehow I have to refresh the HTML page to get the ejs file work on the signal. But If I directly emit it like:
io.sockets.emit('signal')
Then I do not have to refresh the html to get the action work.
How come?
Let me translate the code in plain English.
First case
io.on('connection', function(socket){
socket.emit('signal')
})
Translation: When io is being connected, instruct the connected socket that triggered the connection event to emit 'signal'.
In this case, the io is attached with an event listener that listens for "connection" event, which is fired whenever a socket connects to the io. Therefore, whenever a socket connects to the io, the io instruct the socket to emit a "signal" event.
Why do I need to refresh for it to fire?
Because when you refresh, your computer acts as a socket and is connected to the io onload. Therefore a "connection" event is fired, and it is only fired when a socket connects to the io.
Note: Actually, you do not need to refresh to fire it. You can simply disconnect your internet connection and then reconnect it.
Second case
io.sockets.emit('signal')
Translation: All sockets that are currently connected to io, emit 'signal' event now!
In this case, you are instructing all currently connected sockets to emit the "signal" event. Your computer is a socket connected to the io, so it emits the event.
Note: If you have another device connecting to the same node server, and you use that command, you will see two "signal" events being emitted.
In the first case you're waiting for a "connection" event.
With a refresh of your page, you'll be connected again and finally fire your event.
In the second case, the message will be sent to all clients when you'll start your server.
Here
io.on('connection', function(socket){
}
listen for the connection event for incoming sockets.
if you directly use io.sockets.emit('signal') then you must need event on connection as it check for connection establish or not.
I'm trying to detect whether the websocket is running before allowing clients to connect to it. Consider the following code:
var socket = io.connect('1.1.1.1:1234');
socket.on('connect',function() {
console.log('Client has connected to the server');
});
socket.on('disconnect',function() {
console.log("The client has disconnected from the server");
});
How can I make sure that this block is only called if the server on that IP is actually running and how can I output a message to the users stating that the server is not up?
Thank you
You would need to fire the io.connect() atleast once (consider this as a ping) to detect if server is up, but you can then handle the failure to connect with the socket.on('connect_failed', function () {}) event handler and show a message to user that the 'server is down'. Have a look at Exposed Events for the client
Further, if you would want to reduce the number of times the reconnect is attempted, you can change the socket.io configuration setting for 'reconnect' to false. Checkout Socket.io Configuration for more details