tcpnet

Creates TCP connections between nodes without configuration

npm install tcpnet
15 downloads in the last week
60 downloads in the last month

tcpnet

Creates TCP connections between nodes without configuration.

Installation

npm install tcpnet

If the module dosn't work checkout the node-mdns install instructions.

Example

var tcpnet = require('tcpnet');

// Create a service called my-cluster, for every TCP connection
// pipe the output to the terminal
var service = tcpnet('my-cluster', function (socket) {
  socket.pipe(process.stdout);
});

// For every one second send a message to all other services on the network
var randomId = require('crypto').randomBytes(6).toString('hex');
setInterval(function () {
  console.log('write to ' + service.connections.length + ' nodes');
  service.connections.forEach(function (socket) {
    socket.write('message from ' + randomId  + '\n');
  });
}, 1000);

// Pick a random port, and use all available addresses
service.listen(0, '0.0.0.0');

Not startup a few node.js processes with this code, and you will see this:

$node demo.js

write to 2 nodes
message from a6c953a8c1f1
message from 4eba8c4e76e9
write to 2 nodes
message from a6c953a8c1f1
message from 4eba8c4e76e9

API documentation

In more detail this is a module for creating a fully connected node cluster, that means that each node is aware of all other running nodes by a TCP connection. For the time being this is limited to a local network, that means you can't connect nodes across the internet, however connection nodes on a local network (switch or router) works perfectly. But thoughts are being made.

service = tcpnet(settings, [connection])

This function creates a new service instance.

The settings argument is required and can be a string or an object. Starting with the string case. This is the name of the service and is the only thing there must be shared between all services (nodes).

Example: this code creates two services, they share the same name so they will automaticly be connected.

var serviceA = tcpnet('my-cluster');
    serviceA.listen();

var serviceB = tcpnet('my-cluster');
    serviceB.listen();

The settings argument can also be an object, this provides some more options, there are given by the following paramenters:

  • name required - exactly the same as the string case.
  • uuid optional - each service instance must have a unique ID, if two service instances share the same connection they can't connect and may not be able to reach all other servies, with diffrent IDs. By default the uuid is created by the gmid module. Note there are two requirements for the uuid. One, it must be a hexidecimal string (e.g. BADA55). Two, they all ids must have a fixed length (e.g. AA and CCCCCC won't work).

The next argument connection is a optional function there if given, will be added as a connection event handler.

Example: this code will do the same as the one below:

var service = tcpnet('my-cluster', function (socket) {
  // do something with the TCP socket
});

service.listen();
var service = tcpnet('my-cluster');

service.on('connection', function (socket) {
  // do something with the TCP socket
});

service.listen();

service.listen([port], [address], [callback])

The first argument port is no big surprise, its the port that the service will use to receive other connections. By default port is 0 which is just a random available port assigned by the OS.

The second argument address is the address you want to listen on, by default address is 0.0.0.0 which is all available addresses (localhost and public). Do also note that address can be a domain (e.q. localhost), it will just be resoved to a IP address by a DNS lookup.

Example: 3 ways to listen on only the loopback interface.

service.listen(0, '127.0.0.1');
service.listen(0, '::1');
service.listen(0, 'localhost');

NOTE: because there apear to be a bug in MDNS a public only address (e.q. 192.168.0.198) is not allowed, if you wan't the service to be public you will have to use 0.0.0.0 for the time being.

The third argument callback is just an listening event handler.

service.listen(function () {
  console.log('service is ready');
});

service.address()

This method will return an object containing two properties:

  • port
  • addresses

NOTE: do not use this before the listening has emitted, if you do so it will return null.

Example: show the port and addresses that the service is listening on:

service.listen(0, '0.0.0.0', function () {
  console.log('service is ready and listening on:');

  var info = service.address();
  info.addresses.forEach(function (address) {
    console.log('- ' + address + ':' + info.port);
  });
});

/*  Output could be:
 * - 127.0.0.1:52740
 * - 192.168.0.198:52740
 * - ::1:52740
 * - fe80::5ab0:35ff:fe84:84b1:52740
*/

service.connections

This is a dynamic array containing all online sockets. This means that sockets will be added once the connection event fires and removed once socket close event fires.

Example: multicast a single message from this service to all other online services.

service.connections.forEach(function (socket) {
  socket.write('hallo message to you from me\n');
});

service.close([callback])

This method will close the service and call socket.end() on all online connections.

The optional callback arguments will be assigned as an close event handler.

service.close(function () {
  // everything related to the service is now closed, unless there are other
  // this running node will automaticly shutdown this process.
});

Event: connection

This event is emitted once a new socket becomes online, to detect the when is offline use the socket close event:

Example: how to detect remote service shutdown

service.on('connection', function (socket) {
  socket.once('close', function () {
    console.log('the service is most likely dead now');
  });
});

Event: error

If an error occurres in the server or between establing a TCP connection and the actuall connection event the error event will emit. Be aware that if no error handler exist the error will be throwen.

Example: on one way to handle errors (but almost like just throwing)

service.on('error', function (err) {
  console.error(err.stack);

  // oh no, an error we better just close the service
  service.close(function () {

    // if anything else is running, then it won't be shutdown gracefully
    process.exit(1);
  });
});

Event: listening

Once the service is online this event will emit, note that calling service.address() is quite useless if this event hasn't been emitted.

Event: close

The service is now closed dude to a service.close call.

License

The software is license under "MIT"

Copyright (c) 2012 Andreas Madsen

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

npm loves you