Just wanted to share the effort of the last hour, a method that allows you to discover servers in the local network:
[java]
public static String[] findLocalGames() {
final String addressPrefix;
// calculate the prefix by looking at addresses of local devices
// discarding the loopback device
{
Enumeration<NetworkInterface> dev;
Enumeration<InetAddress> addr;
String address = null;
try {
dev = NetworkInterface.getNetworkInterfaces();
while (dev.hasMoreElements()) {
NetworkInterface ni = dev.nextElement();
if (ni.isLoopback())
continue;
addr = ni.getInetAddresses();
while (addr.hasMoreElements()) {
InetAddress ip = addr.nextElement();
// check for IPv4 (IPv6 uses “:”)
if (ip.toString().contains(".")) {
final String s = ip.toString();
address = s.substring(s.indexOf(’/’) + 1,
s.lastIndexOf(’.’) + 1);
break;
}
}
break;
}
} catch (Exception ex) {
ex.printStackTrace();
}
if (null == address)
return new String[0];
else
addressPrefix = address;
}
// send requests to all 256 local IPs
final LinkedBlockingQueue<String> success = new LinkedBlockingQueue<>();
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 256; i++) {
final int j = i;
pool.execute(new Runnable() {
@Override
public void run() {
String addr = addressPrefix + j;
try {
Client c = Network.connectToServer(addr, PORT);
c.start();
success.add(addr);
c.close();
} catch (Exception e) {
// connection failed
}
}
});
}
try {
pool.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// shut down remaining entries
pool.shutdownNow();
}
// collect answers
return success.toArray(new String[success.size()]);
}
[/java]
The (potentially unsolvable) drawback is, that there is no way to delete the threads waiting for answers for longer then one second directly, so dont be confused, if you write a simple test and the application wont terminate. (It will eventualy) If you want to search for servers with higher delay, change the awaitTermination argument.
PORT is a field or what ever containing the default port.
A minor detail is that you assume that everyone use a class C address, this is not necessarily true, but I guess it is the case in most home-LANs so it’s a reasonable assumption.
Note: while this will work it may take an unreasonably long amount of time to find a server… say if its IP address is 192.168.0.242 or something. In the mean time, it will spawn a lot of threads. Also, it’s a little unfortunate that it spams the server with connections that it’s just going to drop.
For what it’s worth, a more elegant solution is to have clients send out a multicast packet requesting info. If the servers are listening to this multicast address then they can broadcast their connection information. A client need only listen for this info. Just in case a packet is lost, the client can send out a request every second or so until it feels like it’s gotten all of the responses that it’s going to. (You probably don’t want to connect to a server with that many packet drops anyway.)
The only downside of multicast is that certain environments (usually corporate office networks, though) frequently have multicast turned off or limited to parts of the network. For a home LAN, it should be perfect, though. I frequently used that approach here at my house for a variety of services on my network.
What most games do is just send a UDP broadcast and if a server receives it, they reply with their info. This way you don’t have to manually probe the entire 0 - 255 IP range but just send one packet.
@Momoko_Fan said:
What most games do is just send a UDP broadcast and if a server receives it, they reply with their info. This way you don't have to manually probe the entire 0 - 255 IP range but just send one packet.
UDP broadcast on a multicast address. Which is pretty much what I described, I think.
Just as a sidenote, if you’re assuming a class c network, you can skip the 0 and the 255, since those are the net- and the broadcast-adress