6

I am attempting to contact everyone on a LAN to discover which devices are currently using the ip and running my service. Every device running the service will know which other devices are connected when they come online. I have basic networking experience(tcp/udp), but I haven't done much with more complicated communication packages. I wanted to post what I have researched/tried so far and get some expert responses to limit my trial and error time on future potential solutions.

Requirements:

  • Currently using java, but require cross-language communication.
  • Must be done in an acceptable time frame(couple seconds max) and preferably reliably.
  • I would like to use similar techniques for both broadcast and later communications to avoid introducing added complexity of multiple packages/technologies.
  • Currently I am planning on a heartbeat to known ip's to alert that still connected, but I may want to continuously broadcast to lan later.
  • I am interested in using cross-language rpc communication for this service, but this technique doesn't necessarily have to use that.
  • Later communication(non-broadcast) must be reliable.

Research and things attempted:

  • UDP - Worried about cross-language communication, lack of reliable delivery, and would add another way of communicating rather than using one solution like the ones below. I would prefer to avoid it if another more complete solution can be found.

  • Apache Thrift - Currently I have tried to iterate through all potential ip's and try to connect to each one. This is far too slow since the timeout is long for each attempted connection(when I call open). I have yet to find any broadcast option.

  • ZeroMQ - Done very little testing with basic zeromq, but I have only used a wrapper of it in the past. The pub/sub features seem to be useful for this scenario, but I am worried about subscribing to every ip in the lan. Also worried what will happen when attempt to subscribe to an ip that doesn't yet have a service running on it.

Do any of these recommendations seem like they will work better than the others given my requirements? Do you have any other suggestions of technologies which might work better?

Thanks.

pcb
  • 93
  • 7
  • UDP and cross language communication are honestly none of a concern here: all service discovery protocols use UDP nowadays. If there is one which does not, I'd like to hear of it. Also, when speaking of the TCP/IP stack, UDP is level 3 and the other protocols you cite are level 4. – fge Jan 12 '13 at 17:50
  • Oh, and of the commonly used level 3 protocols nowadays, only UDP can do broadcast anyway. TCP can not do it. – fge Jan 12 '13 at 18:03
  • Thanks @fge. I was aware of the difference in the protocol levels, I was just trying to list what I have looked into(perhaps a bit inelegantly). Side question: Given the application layer options, is it common today to still use simple sockets in large production code? It seems rather limiting given the options today. Thanks. – pcb Jan 12 '13 at 18:17
  • Unfortunately, a lot of these existing options surmise that you use HTTP. You effectively want two things: a service discovery mechanism and a service providing mechanism. And the easiest part is the second one... If you wish to use an "HTTP overlay". There does exist Java libraries to harness existing service discovery protocols, but not that many as far as I can see. I am surprised that you didn't stumble upon either UPnP or Bonjour in your research by the way. – fge Jan 12 '13 at 18:30
  • Thanks @fge. Both of those options give me something to think about. I am surprised service discovery is such a complicated problem...I assumed it would be relatively easy. – pcb Jan 12 '13 at 18:57

3 Answers3

9

What you specify is basically two separate problems; discovery/monitoring and a service provider. Since these two issues are somewhat orthogonal, I would use two different approaches to implement this.

Discovery/monitoring

Let each device continuously broadcast a (small) heartbeat/state message on the LAN over UDP on a predefined port. This heartbeat should contain the ip/port (sender) of the device, along with other interesting data, for example an address (URL) to the service(s) this device provides. Choose a compact message format if you need to keep the bandwidth utilization down, for example Protocol Buffers (available in many languages) or JSON for readability. These messages shall be published periodically, for example every 5th second.

Now, let each device listen to incoming messages on the broadcast address and keep an in-memory map [sender, last-recorded-time + other data] of all known devices. Iterate the map say every second and remove senders who has been silent for x heartbeat intervals (e.g. 3 x 5 seconds). This way each nodes will know about all other responding nodes.

You do not have to know about any IP:s, do not need any extra directory server and do not need to iterate all possible IP addresses. Also, sending/receiving data over UDP is much simpler than over TCP and it does not require any connections. It also generates less overhead, meaning less bandwidth utilization.

Service Provider

I assume you would like some kind of request-response here. For this I would choose a simple REST-based API over HTTP, talking JSON. Switch out the JSON payload for Protocol Buffers if your payload is fairly large, but in most cases JSON would probably work just fine.

All-in-all this would give you a solid, performant, reliable, cross-platform and simple solution.

Jakob Möllås
  • 4,239
  • 3
  • 33
  • 61
  • Thanks Jakob, I'll start with that and expand into more complex protocols if needed later. – pcb Jan 13 '13 at 05:39
  • Yes, that sounds like a good plan. ZeroMq is definitely a competent messaging framework but it is not trivial to understand, neither conceptually or in practice (error handling is not a strong point). If you see a need for raw speed and scale, then have a go, it really shines there. As always, try to keep it simple! – Jakob Möllås Jan 13 '13 at 21:42
4

Take a look at the Zyre project in the ZeroMQ Guide (Chapter 8). It's a fairly complete local network discovery and messaging framework, developed step by step. You can definitely reuse the UDP broadcast and discovery, maybe the rest as well. There's a full Java implementation too, https://github.com/zeromq/zyre.

Pieter Hintjens
  • 6,599
  • 1
  • 24
  • 29
  • Thanks @Pieter, code seems well written and straight-forward. When I expand into using zeromq later I will definitely use that as an example. – pcb Jan 13 '13 at 05:42
1

I would use JMS as it can cross platform (for the client at least) You still have to decide how you want to encode data and unless you have specific ideas I would use XML or JSon as these are easy to read and check.

You can use ZeroMQ for greater performance and lower level access. Unless you know you need this, I suspect you don't.

You may benefit from the higher level features of JMS.

BTW: These services do service discovery implicitly. There is no particular need (except for monitoring) to know about IP addresses or whether services are up or down. Their design assumes you want to protected from have to know these details.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • JMS doesn't particularly strike me as a "cross-language communication" protocol... – fge Jan 12 '13 at 18:01
  • Thanks Peter. Using JMS's pub/sub, would every service subscribe to the same topic so when a device comes online he would simply publish once and every other device would be contacted? I am not exactly sure what you mean by service discovery is implicit. Thanks again. – pcb Jan 12 '13 at 18:04