I'm trying to get started with network service discovery for my Java client/server application -- basically, I just want the client to find the server on the same ethernet segment without configuration. I'd like to provide for the future where there are clients are on other platforms. Probably just NETCF and Android. This shouldn't be rocket surgery.
A couple hours of browsing through the options listed here seems to indicate that mdnsjava is the best option at present. I've posted a bit of my research below, but I'm restricted to two links at my current reputation.
I got the Jmdns examples to compile, register, and browse without too much grief... but it simply didn't work reliably. The browser returned IP addresses on the 255.255.254 subnet, on those occasions where it found the service at all.
Mdnsjava gets better reviews, but I've failed utterly to make it run. The examples I've found are code snippets that don't stand on their own, and the javadocs aren't really documentation -- they're just lists of public methods with unnamed (but mandatory) arguments.
Avahi4j has been stuck at v0.1 since 2009. Didn't spend any time on it.
Bonjour apparently requires system libraries on non-Apple platforms.
Upnp, which I admittedly know nothing about, looks like it will take a huge amount of infrastructure to provide my minimal requirement.
Does there exist a compilable, working example of registering a service with mdnsjava? I'm prepared to be told to investigate another library if that's my best course of action in 2015.
Turns out the easiest answer was to roll my own with MulticastSocket, at least for my simple application.
Note to anyone trying to do this: it wasn't much fun trying to make the client work in .NET CF 3.5. There is no asynchronous support, timeouts don't work, and the documentation on multicast support (in CF) is nonexistent. I ended up writing a synchronous client in its own thread. It returns the first couple of servers immediately, and then waits for others for over a minute. Brutal.
import java.net.MulticastSocket;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Main {
public static void main(String[] args) {
if( args.length == 0 ) runClient();
if(args[0].equals("s")) runServer();
else runClient();
}
static String mcastAddr = "239.255.100.100"; // Chosen at random from local network block at http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
static int port = 4446;
public static void runServer() {
while (true) {
try {
MulticastSocket s = new MulticastSocket(port);
InetAddress group = InetAddress.getByName(mcastAddr);
s.joinGroup(group);
byte[] recData = new byte[100];
DatagramPacket receivePacket = new DatagramPacket(recData, recData.length);
s.receive(receivePacket);
String strrec = new String(recData,0,receivePacket.getLength());
print("server received: " + strrec);
print("from: " + receivePacket.getAddress().toString());
if(strrec.equals("Are you there?")) {
String msg = "Here I am";
byte[] msgData = msg.getBytes();
DatagramPacket msgPacket = new DatagramPacket(msgData, msgData.length, receivePacket.getAddress(), receivePacket.getPort());
s.send(msgPacket);
print("server sent: " + msg + "\n");
} else {
print("Didn't send; unrecognized message.");
}
} catch (Exception e) {
print(e.toString());
}
}
}
public static void runClient() {
try {
DatagramSocket s = new DatagramSocket();
String msg = "Are you there?"; // Magic string
byte[] msgData = msg.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(msgData, msgData.length, InetAddress.getByName(mcastAddr), port);
s.send(datagramPacket);
print("client sent: " + msg);
byte[] recData = new byte[100];
DatagramPacket receivePacket = new DatagramPacket(recData, recData.length);
s.receive(receivePacket);
String strrec = new String(recData,0,receivePacket.getLength());
print("client received: " + strrec);
print("from " + receivePacket.getAddress().toString() + " : " + receivePacket.getPort());
System.exit(0);
} catch (Exception e) {
print(e.toString());
}
}
static void print(String s) { System.out.println(s); }
}