Jared Parker
Jared Parker

Reputation: 442

How to detect if two clients/connections are on the same network (nodeJS / express / socket.io)

How would I go about detecting if a connection is on the same network as another connection? This could be from using http, express, socket.io or another library.

This would be used so that a user can quickly join a game hosted by another user in the same house. So other solutions to this would also be appreciated.

Upvotes: 1

Views: 1671

Answers (3)

Jared Parker
Jared Parker

Reputation: 442

With some research I found a method to do this by looking at the Public IP address. I found a useful free API: http://ipify.org, but I wanted to keep it server side. This question answered how to get the IP from a request, but I decided to use request-ip.

Any thoughts on this approach? Obviously there is a very low chance of two networks having the same IPv4 address.

Here is a working example and below is the code.

index.js

const path = require('path');
const express = require("express");
const socket  = require('socket.io');
const requestIp = require('request-ip');

const app = express();
const server = app.listen(8080, () => console.log(`listening on port ${server.address().port}`));

const io = socket(server);

let networks = {};

app.get('/', (req, res) => {
  res.sendFile( path.join( __dirname, 'index.html') );
});

io.on('connection', function (socket) {
  let clientIP = requestIp.getClientIp(socket.request);
  console.log('New connection from ' + clientIP);
  
  if( networks[clientIP] == undefined ){ networks[clientIP] = []; };
  let network = networks[clientIP];
  
  network.push(socket);
  updateNetwork(network);
  
  socket.on('disconnect', function () {
    console.log('Disconnected ' + clientIP);

    network.splice(network.indexOf(socket), 1);
    updateNetwork(network);
  });
  
});

function updateNetwork(network){
  for( let socket of network ){
    socket.emit( 'network-clients', network.length );
  }
}

index.html

<html>
  <head>
    <meta charset="UTF-8">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
    
    <script src="script.js" type="text/javascript"></script>
  </head>
  <body>
    <p>
      Clients Connected on the same network: <span id="network-clients">loading...</span>
    </p>
  </body>
  <script>
    let socket = io.connect(window.location.origin);

    socket.on('network-clients', (data) => {
      document.getElementById('network-clients').innerHTML = data;
    });
  </script>
</html>

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1075337

Network configuration is just too complicated, and in some (or even many) cases opaque¹, for you to use the network for this. Moreover, two people can be in the same house but on different networks (different mobile networks; one on WiFi and the other on mobile; even — in rare cases I'd think — different WiFi networks).

Instead, use prior art: User A creates some kind of unique game identifier (or your system does) and provides that information to User B so User B can join the game. (You may want to have User A confirm them before they're allowed in.) There are a million variations on that theme, but that's the basic, time-tested approach.


¹ Opaque from a browser perspective. Remember the browser sends the information Express sees on the server.

Upvotes: 0

Bill Kervaski
Bill Kervaski

Reputation: 603

You can't because you won't have any way to determine the subnet.

Kind of like having the house number but not the street.

Upvotes: 0

Related Questions