How to handle request disconnect in node/express app - javascript

I have an express/node app and I would like to capture when there is an unexpected interruption in the connection. I tried the following:
req.on('close', function () {
//this captures the browser/tab close scenarios
})
My code does not work in the following scenerios:
Wifi is disconnected
Device shuts down due to lack of power
Is there an event handler that could be leveraged in these scenarios?

You could use sockets to accomplish this. Socket.io is popular.
var io = require('socket.io')({
'port': 8000,
'heartbeat interval': 2000,
'heartbeat timeout' : 3000
});
io.listen(server);
var app_socket = io.of('/foo');
app_socket.on('connection', function(socket) {
// BROWSER CONNECTED
socket.on('disconnect', function(){
// BROWSER DISCONNECTED
});
});
The disconnect event will fire whenever the client loses connection. To connect on the client side it would look like this:
<script media="all" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io.connect('/foo');
socket.on("connect", function(){
// CONNECTED TO SERVER
});
</script>

Related

Can I connect to socket.io server using generic method?

I have a node.js server and I attached socket.io listener to it. The code is like this.
const server = new Hapi.Server();
server.connection({
"port": config.port
});
let io = socketio(server.listener);
io.on("connection", function(socket) {
console.log("A user connected");
socket.on("disconnect", function(){
console.log("A user disconnected");
});
// receive message from client
socket.on("client-server", function(msg) {
console.log(msg);
});
});
// somewhere to emit message
io.emit("server-client", "server to client message");
Normally I use the standard way to connect to the websocket server. An example is like this:
<!DOCTYPE html>
<html>
<head><title>Hello world</title></head>
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('server-client', function(data) {document.write(data)});
socket.emit('client-server', 'test message');
</script>
<body>Hello world</body>
</html>
It works without issue. Now, my colleague wants to connect to the websocket server from his FME server. Based on his research, the only way he can use to connect to a websocket server is using a url like this:
ws://localhost:3000/websocket
My question is: is there a way to connect to socket.io server listener using this type of string?
If not, is there a way to create a websocket server with ws://host:port url and also attach it to my node.js server?
Or, is there a way to connect to socket.io listener in FME server?
To tell Socket.IO to use WebSocket only, add this on the server:
io.set('transports', ['websocket']);
And on the client add this:
var socket = io({transports: ['websocket']});
Now you can only connect to the WebSocket server using ws protocol.

socket.io not emitting event from server to client on connection

I have a very basic setup with socket.io but am having trouble getting my server to send back a message once the connection has been established.
When a connection is established to my server, I want the server to send back a message to the client. I've tried to accomplish this with the following code:
Server
// Modules
var fs = require('fs');
var https = require('https');
// Certificate
var options = {
pfx: fs.readFileSync('<my cert>')
};
// Create Server
httpsServer = https.createServer(options);
// Create websocket
var io = require('socket.io')(httpsServer);
// Listen on a port
httpsServer.listen(4000,function() {
console.log('listening on *:4000');
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.emit('test','you connected');
});
Client
var socket = io('https://<my server>:4000');
When I execute this code, the websocket gets established and my server console shows the message "a user connected". However, the message ['test','you connected'] does not get emitted through the socket.
The only way I've been able to get this to work is to use setTimeout() to wait 500ms before emitting the event, in which case it does work.
Why is that? How can I configure my server to automatically respond with a message as soon as the user connects?
You need to listen to the emitted event, using socket.on(event, callback);
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var socket = io('https://localhost:4000');
//test is the emitted event.
socket.on("test", function(data){
console.log(data); //"you connected"
});
</script>

Call event from native WebSocket to Socket.IO server

I have this socket.io server:
var io = require('C:\\Program files\\nodejs\\node_modules\\socket.io').listen(55555);
io.set('destroy upgrade', false);
io.sockets.on('connection', function (socket) {
socket.on('sayHello', function () {
console.log('Hello client!');
socket.emit('sayHello');
});
socket.on('disconnect', function () {
console.log('Goodbye!');
});
});
And I want to connect to the server using the WebSocket class like this:
var socket = new WebSocket('ws://localhost:55555');
I get the connection, but I want to know how can I call an event of the server, example: "sayHello", is that possible? or does Socket.IO use some kind of token in order to avoid spoofing? Thank you!
You should be able to use the socket.io-client module directly from node. It handles the socket.io protocol and everything for you, just like the browser, except in node.

socket.io/node.js detecting if server is down

Is there something that I can do on the client side to detect that the socket.io websocket is not available? Something along the lines of:
server starts as per usual
clients connect
messages are sent back and forth between server and client(s)
server shuts down (no longer available)
warn the connected clients that the server is not available
I tried to add the 'error' and 'connect_failed' options on the client side but without any luck, those didn't trigger at all. Any ideas from anyone how I can achieve this?
The disconnect event is what you want to listen on.
var socket = io.connect();
socket.on('connect', function () {
alert('Socket is connected.');
});
socket.on('disconnect', function () {
alert('Socket is disconnected.');
});
If you want to be able to detect that the client was not able to connect to the server, then try using connect_error. This works for me with socket.io-1.3.5.js. I found this in https://stackoverflow.com/a/28893421/2262092.
Here's my code snippet:
var socket = io.connect('http://<ip>:<port>', {
reconnection: false
});
socket.on('connect_error', function() {
console.log('Failed to connect to server');
});
hit this bug during my development and noticed my event calls were doubling up every time i reset the server, as my sockets reconnected. Turns out the solution that worked for me, which is not duping connections is this
var socket = io.connect();
socket.on('connect', function () {
console.log('User connected!');
});
socket.on('message', function(message) {
console.log(message);
});
( Found this at https://github.com/socketio/socket.io/issues/430 by KasperTidemann )
Turns out, it was becuase I put the 'message' listener inside the 'connect' function. Seating it outside of the listener, solves this problem.
Cheers to Kasper Tidemann, whereever you are.
Moving on!!
connect_error didn't work for me (using Apache ProxyPass and returns a 503).
If you need to detect an initial failed connection, you can do this.
var socket;
try {
socket = io();
}
catch(e) {
window.location = "nodeServerDown.php";
}
Redirects the user to a custom error page when the server is down.
If you need to handle a disconnect after you've connected once.
You do this:
socket.on('disconnect', function() {
//whatever your disconnect logic is
});

socket.io - 'connect' event does not fire on the client

I am trying to get started with node.js and socket.io.
I have a very (very) simple client-server test application and i can't get it to work.
The system is set up on a windows machine with an apache server.
The apache is running on port 81 and the the socket.io is set up to listen to port 8001
Server - server.js
var io = require('socket.io').listen(8001);
io.sockets.on('connection', function (socket) {
console.log('\ngot a new connection from: ' + socket.id + '\n');
});
Client - index.html
<!DOCTYPE html>
<html>
<head>
<title>node-tests</title>
<script type="text/javascript" src="http://localhost:8001/socket.io/socket.io.js"> </script>
<script type="text/javascript">
var socket = io.connect('http://localhost', { port: 8001 });
socket.on('connect', function () {
alert('connect');
});
socket.on('error', function (data) {
console.log(data || 'error');
});
socket.on('connect_failed', function (data) {
console.log(data || 'connect_failed');
});
</script>
</head>
<body>
</body>
</html>
After starting my server using node server.js the standard (expected) output is written to the server console:
info: socket.io started
When I open index.html in the browser (chrome in my case - didn't test on other browsers) the following log is written to the server console:
info: socket.io started
debug: served static content /socket.io.js
debug: client authorized
info: handshake authorized 9952353481638352052
debug: setting request GET /socket.io/1/websocket/9952353481638352052
debug: set heartbeat interval for client 9952353481638352052
debug: client authorized for
got a new connection from: 9952353481638352052
debug: setting request GET /socket.io/1/xhr-polling/9952353481638352052?t=1333635235315
debug: setting poll timeout
debug: discarding transport
debug: cleared heartbeat interval for client 9952353481638352052
debug: setting request GET /socket.io/1/jsonp-polling/9952353481638352052?t=1333635238316&i=0
debug: setting poll timeout
debug: discarding transport
debug: clearing poll timeout
debug: clearing poll timeout
debug: jsonppolling writing io.j[0]("8::");
debug: set close timeout for client 9952353481638352052
debug: jsonppolling closed due to exceeded duration
debug: setting request GET /socket.io/1/jsonp-polling/9952353481638352052?t=1333635258339&i=0
...
...
...
In the browsers console I get:
connect_failed
So it seems like the client is reaching the server and trying to connect, and the server is authorizing the handshake but the connect event is never fired in the client, instead the connect method reaches its connect timeout and max reconnection attempts and gives up returning connect_failed.
Any help\insight on this would be helpful.
Thank you
Make sure that both client and server have same major version of socket.io. For example, combination of socket.io#2.3.0 on server and socket.io-client#3.x.x at client leads to this case and the 'connect' event is not dispatched.
//Client side
<script src="http://yourdomain.com:8001/socket.io/socket.io.js"></script>
var socket = io.connect('http://yourdomain.com:8001');
//Server side
var io = require('socket.io').listen(8001);
io.sockets.on('connection',function(socket) {
`console.log('a user connected');`
});
Client side:
The client side code requests the client version of socket IO from the same file that gives you server side socketIO. Var socket will now have all the methods that are available with socketIO, such as socket.emit or socket.on
Server Side:
same as client side, making the socketIO methods available for use under var io.
Change in the frontend (client):
var socket = io.connect(http://myapp.herokuapp.com);
to
var socket = io.connect();
After many hours of dealing with various clients (Chrome, Firefox browsers and Phonegap app) that did not register connection to the server properly (i.e. the server registered the websocket connection successfully in its logs, but the frontend did not register the connection event), I tried #Timothy's solution from the comments and now everything works again on heroku and on localhost.
With socketio 2.3.0 you have to use socket.on('connect')
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io({
transports: ['polling']
});
console.log("created",socket);
socket.on('connect', function(data){ // <-- this works
console.log("socket ON connect",data);
});
socket.on('connection', function(data){ // <-- this fails
console.log("socket ON connection",data);
});
</script>
Use autoConnect: false option while creating: io(... { autoConnect: false }), subscribe on your events and invoke io.connect().
Try the following:
Change
var socket = io.connect('http://localhost', { port: 8001 });
to
var socket = io.connect('http://localhost:8001');
Try using this:
Server.js
var http = require("http").createServer(), io = require("socket.io").listen(http);
http.listen(8001);
io.sockets.on("connection", function(socket){
console.log("Connected!");
socket.emit("foo", "Now, we are connected");
});
index.html
<script src="http://localhost:8001/socket.io/socket.io.js"></script>
<script>
var i = io.connect("http://localhost:5001");
i.on("foo", function(bar){
console.log(bar);
})
</script>

Categories