Reputation: 442
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
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
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
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