Occasionally I want to transfer a file from my Linux desktop machine to one of my Android-based devices via my home network. Shouldn't be a problem, there are lots of networking protocols for this, right? In practice, many solutions you think of aren't convenient enough for daily use.
Services like Ubuntu One or Dropbox work well, but you don't want to send larger files across the internet. Sharing via Bluetooth might work for small files, but my desktop machine doesn't support Bluetooth. Using my servehttp script to publish a directory via HTTP works technically, but you have to know the (dynamic) IP address of the desktop machine. While I could assign a static address, it's pretty inconvenient having to deal with IP addresses (even more so with IPv6).
A perfectly fine set of standards for solving the addressing problem is Zeroconf, modeled after Apple's Bonjour. Using its Multicast DNS (MDNS) protocol, a device can look up a host's name by sending a MDNS query to the local network. The device owning the host name responds with its IP address. Since this is just DNS over multicast, it integrates well with your system's resolver. Also, hosts can announce services to the network. On recent linux distributions you need packages avahi-daemon and the resolver plugin package libnss-mdns. Then you should be able to look up your host on your local network (try ping HOST.local). Unfortunately, Android doesn't support Zeroconf out of the box.
A widely deployed alternative to Zeroconf is Universal Plug and Play (UPnP). It provides service discovery through announcements like Zeroconf, but has never been properly standardized. Hosts announce services via Simple Service Discovery Protocol (SSDP), a multicast-based UDP protocol. SSDP announcements are basically HTTP extended with a NOTIFY method:
NOTIFY * HTTP/1.1 HOST: 188.8.131.52:1900 CACHE-CONTROL: max-age=1800 LOCATION: http://192.168.2.103:49152/description.xml NT: urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1 NTS: ssdp:alive SERVER: Linux/2.6.38-11-generic, UPnP/1.0, Portable SDK for UPnP devices/1.6.6 X-User-Agent: redsonic USN: uuid:898f9738-d930-4db4-a3cf-0015c5c15a3f::urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1
It looks a bit like a redirect; in fact you can download a service description from http://192.168.2.103:49152/description.xml.
There are several media servers that support UPnP. Here's how you share a file system directory on my desktop machine using ushare:
matthias@amy ~ $ ushare -c /tmp/share/ Warning: can't parse file "/etc/ushare.conf". Recheck uShare's configuration and try again ! uShare (version 1.1a), a lightweight UPnP A/V and DLNA Media Server. Benjamin Zores (C) 2005-2007, for GeeXboX Team. See http://ushare.geexbox.org/ for updates. Listening on telnet port 1337 Initializing UPnP subsystem ... UPnP MediaServer listening on 192.168.2.103:49152 Sending UPnP advertisement for device ... Listening for control point connections ... Building Metadata List ... Looking for files in content directory : /tmp/share/ Found 2 files and subdirectories.
This works well for one-off sharing of media files. You can also run ushare as a system service on a fixed set of directories. Obviously, this is only viable for local, trusted networks (have a look at ushare's web console for even more reasons).
On my Android devices, I use BubbleUPnp to stream music or videos (in supported formats) and optionally download them. Unfortunately, most UPnP apps seem to be media players and ushare doesn't seem to serve document files (I want my ebooks, dammit).
This means, right now I'm stuck with assigning a static IP address to my desktop machine and serve files via HTTP. Or are there better solutions?