npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@the3rdc/netshout

v1.4.3

Published

Broadcast and subscribe to simple messages over node's net sockets.

Downloads

10

Readme

NetShout

Broadcast and subscribe to simple messages over node's net sockets.

Getting Started

npm i @the3rdc/netshout
const NetShout = require('@the3rdc/netshout');

var strongPeer = new NetShout();

var weakPeer = new NetShout();

weakPeer.subscribe('sampleEvent',function(body){
  console.log("I Received:", body);
});

strongPeer.startHosting(1987,function(){
  weakPeer.connectTo('localhost',1987, function(){
    strongPeer.shout('sampleEvent',"Hello everyone!");
  });
});

Why This Exists

I needed a way to abstract the connection of arbitray nodes, and allow one way communication (out) from any node to it's neighbors.

It needed to function both on a linux server and in an "electron" or other native framework app on Mac, Windows, etc.

It needed to allow for some of the peers to be unable to receive incoming connections (ex: firewalls).

Documentation (especially good examples) on using Node JS "net" package were hard to find, and abstractions for inter-node communication were either too specific or included features that I did not need.

Documentation

Instantiation

const NetShout = require('@the3rdc/netshout');

var peer = new NetShout();

Hosting a Connection

var strongPeer = new NetShout();

var port = 1987;

strongPeer.startHosting(port, function(){
  console.log("I'm ready to accept connections on port " + port);
});

Connecting to a Host

var peer = new NetShout();
var address = '127.0.0.1';
var port = 1987;

peer.connectTo(address, port, function(){
  console.log("I'm connected to " + address + ':' + port);
});

Closing Connections

//closes the specified connection
peer.disconnectFrom(address, port);

//closes all connections
peer.disconnectAll();

//stops accepting incoming connections
peer.stopHosting();

//wrapper for diconnectAll() followed by stopHosting()
peer.shutDown();

Strong vs Weak Peers

A "Strong" peer in NetShout is simply a peer that can accept incoming connections. It can act as a host using the .startHosting() function. A "Weak" peer is one that can connect "out" to other nodes, but cannot let them connect "in" (ex: behind a network firewall). A node may be considered a "Strong Peer" within a local network, and a "weak" peer in relation to an external network. In order for two nodes to communicate, at least one of them must be "Strong".

However, once two nodes are connected, there is no difference in functionality. Both and can send messages via .shout() and subscribe to messages via .subscribe().

It's tempting to think of Strong and weak peers as a "Client/Server" framework, and this is accurate for a relationship between a single strong and weak peer. However, strong peers can connect to other strong peers, and a weak peer can connect to more than one strong peer.

It is likely that a given node's neighbors will be a mix of strong and weak peers.

Broadcast a Message

This will send a message to all neighbors. Type can be any string, and should be used to categorize the message.

(This will always send to all neighbors. NetShout does not currently provide a method for messaging a single peer.)

var type = 'example';
var message = 'hello there!';
peer.shout(type, message);

Subscribe to Message

The callback wil be fired when a message with the specified type is recieved from any neighbor.

(This will fire for all neighbors. NetShout does not currently provide a method for subscribing to a single peer.)

peer.subscribe('example',function(message){
  console.log("I received the message: ", message);
});

Multi Peer Example

In the below example, we create 2 "strong" and 2 "weak" peers. Both strong peers begin hosting connections, and both weak peers connect to both of them. The first strong peer also connects to the second.

You should see that when strongPeer1 sends out a message with .shout(), all three of the other peers receive it. It does not matter that strongPeer1 connected to strongPeer2 as opposed to the other way around. Once established, all connections can send from either side.

You should see that when weakPeer1 sendso ut a message with .shout(), only the two StrongPeers recieve it. This represents a scenario where some peers are not able to host - so weakPeer1 has a connection to both strong peers, but no connection to weakPeer2.

(Note, either strong peer could create a path from weakPeer1 to weakPeer2 but re-broadcasting their messages.)

const NetShout = require('@the3rdc/netshout');

var strongPeer1 = new NetShout();
var port1 = 1987;
var strongPeer2 = new NetShout();
var port2 = 1337;

var weakPeer1 = new NetShout();
var weakPeer2 = new NetShout();

function startHosing(){
  return new Promise(function(resolve, reject){
    var ready1 = false;
    var ready2 = false;
    strongPeer1.startHosting(port1, function(){
      //strong peer 1 is ready to receive connections
      ready1 = true;
      if(ready2){
        resolve();
      }
    });
    strongPeer2.startHosting(port2, function(){
      //strong peer 2 is ready to receive connections
      ready2 = true;
      if(ready1){
        resolve();
      }
    });
  });
}

function getConnected(){
  return new Promise(function(resolve, reject){
    var ready1 = false;
    var ready2 = false;
    var ready3 = false;
    var ready4 = false;
    var ready5 = false;

    weakPeer1.connectTo('localhost', port1,function(){
      ready1 = true;
      if(ready1 && ready2 && ready3 && ready4 && ready5){
        resolve();
      }
    }); //connected to strong 1
    weakPeer1.connectTo('localhost', port2,function(){
      ready2 = true;
      if(ready1 && ready2 && ready3 && ready4 && ready5){
        resolve();
      }
    }); //connected to strong 2

    weakPeer2.connectTo('localhost', port1,function(){
      ready3 = true;
      if(ready1 && ready2 && ready3 && ready4 && ready5){
        resolve();
      }
    }); //connected to strong 1
    weakPeer2.connectTo('localhost', port2,function(){
      ready4 = true;
      if(ready1 && ready2 && ready3 && ready4 && ready5){
        resolve();
      }
    }); //connected to strong 2

    strongPeer1.connectTo('localhost',port2,function(){
      ready5 = true;
      if(ready1 && ready2 && ready3 && ready4 && ready5){
        resolve();
      }
    }); //connected to strong 2
  });
}

startHosing().then(function(){
  getConnected().then(function(){
    weakPeer1.subscribe('ping',function(message){
      console.log('weak1 got: ', message);
    });
    weakPeer2.subscribe('ping',function(message){
      console.log('weak2 got: ', message);
    });
    strongPeer1.subscribe('ping',function(message){
      console.log('strong1 got: ', message);
    });
    strongPeer2.subscribe('ping',function(message){
      console.log('strong2 got: ', message);
    });

    strongPeer1.shout('ping','hello');
    weakPeer1.shout('ping','hi yourself');
  });
});

Version 1 Roadmap

  • Handle deduping of neighbors (currently if I connect to you, then you connect to me, we'll each list eachother twice...)

Roadmap for v2.0

(Seems a little soon for a v2, but these will be breaking changes, so...)

  1. Replace callBack pattern on .startHosting() and .connectTo() with a promise pattern.
  2. Add a context variable to subscription callbacks to identify which peer the message came from.
  3. Add the ability to message a specific neighbor instead of everyone.
  4. Add the ability to message everyone except the node you received a message from (within a subscription callback).