jean28
jean28

Reputation: 102

Node.js Processes Don't Detect Port is Already Being Used

I am trying to have two different Node processes (using Cluster) try to become servers to a Port. However, whenever the second process gets to the port, it doesn't detect that the port is being used.

I suspect the reason why they are not detecting if the port is open or not is due to the nature of callbacks (I'm detecting if the port is used or not using the portInUse function, so it is fetched asynchronously, and might cause some type of conflict later on).

Here is the code:

var cluster = require('cluster');
var net = require('net');

var PORT = 1337;
var list = {};
var portIsBeingUsed = false;

// Variable that detects if the port is in use.
var portInUse = function(port, callback) {
  var server = net.createServer(function(socket) {
    socket.write('Echo server\r\n');
    socket.pipe(socket);
  });

  server.listen(port, 'localhost');
    server.on('error', function (e) {
    callback(true);
  });

    server.on('listening', function (e) {
  server.close();
  callback(false);
    });
};

if (cluster.isMaster) {
  for (var i = 0; i < 2; i++) {
    cluster.fork();
  }

   Object.keys(cluster.workers).forEach(function(id) {
    console.log("I am running with ID : "+ cluster.workers[id].process.pid);
    list[cluster.workers[id].process.pid] = 0;
  });

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
}  else { // Rest of the logic with all Processes goes here.

      // Get the Process ID of the current process in execution.
      var pid = cluster.worker.process.pid;
      console.log("This is process " + pid + " working now.\n");

      // Verify if Port is being used. 
      portInUse(PORT, function(returnValue) {
        if(returnValue) { // Become a Client to the Server
          console.log("port " + PORT + " is being used.\n\n");
          becomeClient(pid);
        } else { // Become a Server
          console.log("port" + PORT + " is not being used.\n\n");
          becomeServer(pid);
        }
      });
}

function becomeServer(pid) {
  var server = list[pid];

  server = net.createServer(function (socket) {
    socket.write('Hello Server 1\r\n');
    socket.end("hello");
    console.log("Someone connected to Server 1. \n");
    socket.pipe(socket);
  });

  server.listen(PORT, function(){
    console.log("Process " + pid + " has become the Server on Port " + PORT);
  });

  server.on("error", function() {
    console.log("there was an error on Process " + pid);
    console.log("this error was becoming a Server.");
  });
}

function becomeClient(pid) {
  var client = list[pid];

  client = net.connect({port: PORT}, function() {
    list[pid].write("I am connected to the port and my pid is " + pid);
  });

  client.on('data', function(data) {
    console.log(data.toString());
    list[pid].end();
  });

  client.on('end', function() {
    console.log('disconnected from server');
  });
}

And here is the output:

enter image description here

So the first process (In this case Process 9120) becomes the server on port 1337, but then the second process doesn't detect that the port is being used and somehow becomes the server as well (I would expect an EADDRINUSE here, not sure why it isn't showing any errors).

Any help or clarification as to why this isn't working would be greatly appreciated.

Thanks,

Upvotes: 0

Views: 330

Answers (2)

Aaron Dufour
Aaron Dufour

Reputation: 17535

A large part of the point of cluster involves port sharing, so that you can have multiple workers take turns serving requests. The worker processes just request a port from the master, which actually opens the port, and then the master hands requests back to any workers that have requested that port.

Upvotes: 1

mscdex
mscdex

Reputation: 106746

This is expected behavior and it is how the cluster module works (by default). It's what allows incoming requests to the same port to be easily distributed among the available workers.

Upvotes: 1

Related Questions