How I can CLOSE socket.io server? - node.js

Here is my code:
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
var sockets = [];
io.sockets.on('connection',function(socket){
console.log('client connecting');
sockets.push(socket);
});
server.listen(5000);
setTimeout(function(){
io.server.close(); // same as server.close()
sockets.forEach(function(socket){
socket.disconnect(true);
});
},5000);
After 5 sec timeout I still receive connections... How to stop it? I want to just KILL it forever!

According to the source code (see disconnect(close) method), it requires true parameter for closing underlying connection.
socket.disconnect(true);

You can use
socket.destroy();
You might be receiving connections because of reconnection attempts made by clients.

Related

Using Socket.io, connections keep dropping

I'm using Socket.io to do some communication between a phone and a web page, and I'm having issues with the server constantly dropping connections. I've seen a lot of other people posting about Socket.io where their connections drop after being idle for about 5 minutes or so, but this is a connection that has constant information being emitted back and forth, and the longest I've been able to maintain a connection is about 30 seconds.
The server side code I'm running is:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('create', function (room) {
socket.join(room);
});
socket.on('player-move', function(msg){
roomId = msg['room'];
move = msg['action'];
socket.broadcast.to(roomId).emit('player-move', move);
});
socket.on('disconnect', function() {
console.log('someone has disconnected');
});
});
http.listen(443, function(){
console.log('listening on *:443');
});
The client side is pretty basic emit events. Here's an example:
$( "#arrow-left" ).on( "touchstart", function(){
var senddata = { "room": roomId, "action": "d-l" };
socket.emit( "player-move", senddata );
});
Everything seems to be running fine until 5-30 seconds after everything starts and then the connection just drops. The connection usually starts up again, but after 5-10 seconds. Has anyone had similar issue occurring? Would this potentially be an issue with the server rather than the code? I've done similar things before on different servers with Socket.io and haven't had this kind of connection issue. Any help or direction to go in would be appreciated. Thanks!
I had the same problem with another library called ws and I tried to handle the disconnection method properly by deleting the specific client sending the disconnection request from a array of clients. I don't exactly know how, but it solved my problem.
clients = []
io.on('connection', function(socket){
clients.push(socket);
// above methods
socket.on('disconnect', function(){
console.log("disconnected");
deleteFromArray(clients, socket.id);
});
});
function deleteFromArray(arr, element) {
position = arr.indexOf(element);
arr.splice(position, 1);
}

socket.IO can only connect one client (browser) at a time

I am having a problem of using socket IO to connect my server to the client(http website).
On the client, I have a button that when pressed, sends data to the server. However, this only works with one client.
If I have two clients, the first person to open the http website gets the socket IO connection, while the second person can open the page, but can't send any data to the server.
On the client side:
var socket = new io.connect('ServerIP:8090');
socket.on('message', function(obj){
if ('buffer' in obj){
//ignore this
} else message(obj);
});
On server side:
var io = io.listen(server)
, buffer = [];
io.on('connection', function(client)
{
client.send({ buffer: buffer });
client.broadcast.send({ announcement: client.sessionId + ' connected' });
chatGuests.push(client);
client.on('message', function(message){
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.broadcast.send(msg);
});
client.on('disconnect', function(){
client.broadcast.send({ announcement: client.sessionId + ' disconnected' });
});
Instead of using client.broadcast.send(something) and client.send(something) use io.emit('eventName', something). Also, for setting up the server with the variable io use
var socket = require('socket.io');
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var io = socket.listen(server);
And then after your code:
server.listen(8090);
This allows you to use the node.js module express, which allows additional communication between the client and server (but doesn't require you to rewrite your socket.io code).
For your client code, instead of using:
socket.on('message', function(obj){
//Do something
});
Use:
socket.on('eventName', function(something){
//Do something
});
This works for multiple kinds of data passing, not just messages. You can multiple event listeners to each do different things

Force close all connections in a node.js http server

I have an http server created using:
var server = http.createServer()
I want to shut down the server. Presumably I'd do this by calling:
server.close()
However, this only prevents the server from receiving any new http connections. It does not close any that are still open. http.close() takes a callback, and that callback does not get executed until all open connections have actually disconnected. Is there a way to force close everything?
The root of the problem for me is that I have Mocha tests that start up an http server in their setup (beforeEach()) and then shut it down in their teardown (afterEach()). But since just calling server.close() won't fully shut things down, the subsequent http.createServer() often results in an EADDRINUSE error. Waiting for close() to finish also isn't an option, since open connections might take a really long time to time out.
I need some way to force-close connections. I'm able to do this client-side, but forcing all of my test connections to close, but I'd rather do it server-side, i.e. to just tell the http server to hard-close all sockets.
You need to
subscribe to the connection event of the server and add opened sockets to an array
keep track of the open sockets by subscribing to their close event and removing the closed ones from your array
call destroy on all of the remaining open sockets when you need to terminate the server
You also have the chance to run the server in a child process and exit that process when you need.
For reference for others who stumble accross this question, the https://github.com/isaacs/server-destroy library provides an easy way to destroy() a server (using the approach described by Ege).
I usually use something similar to this:
var express = require('express');
var server = express();
/* a dummy route */
server.get('/', function (req, res) {
res.send('Hello World!');
});
/* handle SIGTERM and SIGINT (ctrl-c) nicely */
process.once('SIGTERM', end);
process.once('SIGINT', end);
var listener = server.listen(8000, function(err) {
if (err) throw err;
var host = listener.address().address;
var port = listener.address().port;
console.log('Server listening at http://%s:%s', host, port);
});
var lastSocketKey = 0;
var socketMap = {};
listener.on('connection', function(socket) {
/* generate a new, unique socket-key */
var socketKey = ++lastSocketKey;
/* add socket when it is connected */
socketMap[socketKey] = socket;
socket.on('close', function() {
/* remove socket when it is closed */
delete socketMap[socketKey];
});
});
function end() {
/* loop through all sockets and destroy them */
Object.keys(socketMap).forEach(function(socketKey){
socketMap[socketKey].destroy();
});
/* after all the sockets are destroyed, we may close the server! */
listener.close(function(err){
if(err) throw err();
console.log('Server stopped');
/* exit gracefully */
process.exit(0);
});
}
it's like Ege Özcan says, simply collect the sockets on the connection event, and when closing the server, destroy them.
I've rewriten original answers using modern JS:
const server1 = http.createServer(/*....*/);
const server1Sockets = new Set();
server1.on("connection", socket => {
server1Sockets.add(socket);
socket.on("close", () => {
server1Sockets.delete(socket);
});
});
function destroySockets(sockets) {
for (const socket of sockets.values()) {
socket.destroy();
}
}
destroySockets(server1Sockets);
My approach comes from this one and it basically does what #Ege Özcan said.
The only addition is that I set a route to switch off my server because node wasn't getting the signals from my terminal ('SIGTERM' and 'SIGINT').
Well, node was getting the signals from my terminal when doing node whatever.js but when delegating that task to a script (like the 'start' script in package.json --> npm start) it failed to be switched off by Ctrl+C, so this approach worked for me.
Please note I am under Cygwin and for me killing a server before this meant to close the terminal and reopen it again.
Also note that I am using express for the routing stuff.
var http=require('http');
var express= require('express');
var app= express();
app.get('/', function (req, res) {
res.send('I am alive but if you want to kill me just go to /exit');
});
app.get('/exit', killserver);
var server =http.createServer(app).listen(3000, function(){
console.log('Express server listening on port 3000');
/*console.log(process);*/
});
// Maintain a hash of all connected sockets
var sockets = {}, nextSocketId = 0;
server.on('connection', function (socket) {
// Add a newly connected socket
var socketId = nextSocketId++;
sockets[socketId] = socket;
console.log('socket', socketId, 'opened');
// Remove the socket when it closes
socket.on('close', function () {
console.log('socket', socketId, 'closed');
delete sockets[socketId];
});
// Extend socket lifetime for demo purposes
socket.setTimeout(4000);
});
// close the server and destroy all the open sockets
function killserver() {
console.log("U killed me but I'll take my revenge soon!!");
// Close the server
server.close(function () { console.log('Server closed!'); });
// Destroy all open sockets
for (var socketId in sockets) {
console.log('socket', socketId, 'destroyed');
sockets[socketId].destroy();
}
};
There is now a closeAllConnections() method in v18.2.0

SocketIO broadcasting too fast

I would like to broadcast a single message to every client every second (think about it as custom heartbeat mechanism).
So the NodeJS app is started, sockets are created and when I connect from the client app the heartbeat messages are broadcasted. I'm still developing the client application and that means hitting F5 all the time and reloading the application. The new client SocketIO connection is created on load and this results in heartbeat messages coming to client app with rate much higher than 1 message/sec.
There is nothing special about the code - server side:
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(8080);
io.sockets.on('connection', function(socket) {
...
setInterval(function() {
console.info('broadcasting heartbeat');
socket.broadcast.emit('heartbeat', /* custom heartbeat*/);
}, 1000);
...
});
Client side:
var socket = io.connect('localhost', { 'reconnect': false, port: 8080 });
socket.on('heartbeat', function(data) { console.log('heartbeat'); });
Can anybody give me some advice what's wrong? Thanks
No need to startup up an interval each time. You can store the intervalID, and even clear it out with clearInterval(INTERVAL); when it's not needed.
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(8080);
var INTERVAL;
io.sockets.on('connection', function(socket) {
...
if (!INTERVAL) {
INTERVAL = setInterval(function() {
console.info('broadcasting heartbeat');
socket.broadcast.emit('heartbeat', /* custom heartbeat*/);
}, 1000);
}
...
});

How does one properly shutdown socket.io / websocket-client?

I'm trying to create a test using LearnBoost's socket.io and the node-websocket-client. Communication between the client and server work great. After all communication is done, I close both the client and the server. Yet the program hangs, waiting on some unknown callback. Two questions:
What is the following program waiting for?
Is there a tool for diagnosing outstanding callbacks in node programs?
var connect = require('connect'),
io = require('socket.io'),
WebSocket = require('websocket-client').WebSocket;
var port = 7111;
var server = connect.createServer();
var socket = io.listen(server);
socket.on('connection', function(client) {
client.send('Welcome!');
client.on('message', function(message) {
console.log(message);
});
client.on('disconnect', function() {
console.log('closing');
server.close();
});
});
server.listen(port, function() {
var ws = new WebSocket('ws://localhost:' + port + '/socket.io/websocket');
ws.onmessage = function(message) {
console.log(message.data);
};
setTimeout(function() {
ws.send('~m~3~m~Yo!');
ws.close();
}, 10);
});
EDIT: changed the variable name of the WebSocket to ws to avoid confusion
var socket = io.listen(server);
You've created a socket on a port. You've never closed it.
socket.server.close() closes your (socket.io) socket.
When in doubt read the socket.io github examples
socket.server === server It's the server you pass in, in the liste statement so it's closed. I'm not sure what it's waiting for.
Below a way to shutdown all the connections and be able to run multiple expresso tests (using socket.io and socket.io-client).
The solution is tricky and buggy but works on 0.8.5. The main problem is regarding the library to use websockets (node-websocket-client).
Currently, on socket.io, the OS contributors have patched the websocket client. So, we must do the same on our socket.io-client npm package to be able to use finishClose method on the socket client side. Socket.io-client uses the websocket library as npm package, so you must find the file (websocket.js) and substitute it with the same on socket.io.
Afterwards, you could use finishClose method to ensure the connections are closed and with some custom server/client socket settings, the tests will run correctly.
var io = require("socket.io").listen(port);
io.set('close timeout', .2);
io.set('client store expiration', .2);
var client = require("socket.io-client").connect( "http://localhost", { port: port , 'reconnect': false, 'force new connection': true});
client.on('connect', function() {
client.disconnect();
});
client.on('disconnect', function() {
client.socket.transport.websocket.finishClose();
io.server.close();
});
io.server.on('close', function() {
setTimeout( function() {
done();
}, 500);
});
Hope, somebody can help.
The program is waiting because socket.io (server) is still listening for incoming connections. I don't know of any way to stop listening.

Resources