1

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.

Jared Parker
  • 390
  • 2
  • 3
  • 16
  • What if they're in the same house but on different mobile networks? Or one is on WiFi and the other on mobile? Do they not get to play? :-) – T.J. Crowder Nov 20 '20 at 15:58

3 Answers3

1

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>
Jared Parker
  • 390
  • 2
  • 3
  • 16
0

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.

Bill Kervaski
  • 542
  • 6
  • 17
  • Is there not a way to check by comparing IP addresses? I've seen sites before such as voting where accessing it again on same network will not allow you to vote again. – Jared Parker Nov 20 '20 at 17:01
  • You can certainly check the IP address but no way of knowing the subnet; so no way of knowing the originating network. Assuming 1.2.3.4 is on the same network as 1.2.3.5 is bad practice as 1.2.3.5 could be an entirely different network. – Bill Kervaski Nov 23 '20 at 16:37
0

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.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Using a unique game identifier was going to be the default way to join, but this idea of checking if they're on the same network would be an ease of use feature. – Jared Parker Nov 20 '20 at 17:01
  • 1
    @JaredParker - Ah, that makes sense. Perhaps if you have established links between accounts or something. (But you may have thought of that, too -- still doesn't change the fact it'd be convenient if two people are standing next to each other and don't have a prior connection to just find games "nearby.") Maybe someday [web bluetooth](https://www.w3.org/community/web-bluetooth/) will be a thing. – T.J. Crowder Nov 20 '20 at 17:02
  • 1
    We can only hope. Thanks for the help and ideas :) – Jared Parker Nov 20 '20 at 17:25