It may not be obvious if you take a look at the Paho MQTT (http://mqtt.org) C client libraries (http://www.eclipse.org/paho/) , but my intention all along was to avoid proliferation of C APIs.
When I first started writing a C client for MQTT, around 2008, there was one other C MQTT API that I knew about – the now withdrawn IA93 (http://www-01.ibm.com/support/docview.wss?uid=swg24006525). With all respect to the author, this had an interface which I did not want to copy. Firstly, there were the variable length option structures, which meant that you had to copy topic strings, for instance, into their correct location in the structure before making the API call. Secondly, there was the overly complicated method of setting up the API to operate with background threads.
IA93 did have one feature that I felt it was desirable to copy: the ability to work using no background threads. As MQTT is intended for embedded devices, we would like the library to work in very simple environments.
My other starting point was the MQTT Java API at the time, I saw no reason why the C API should be much more difficult to use. So I set out to create a C API that was close to the Java API, with the addition that it could be optionally run with no background threads. This became the MQTTClient API (http://www.eclipse.org/paho/files/mqttdoc/Cclient/index.html). The parameters are similar to the Java API – no unnecessary variable length structures. The method I chose to indicate whether you want background threads or not is to simply make a call to MQTTClient_setCallbacks(). Asking for callbacks means that you have to have a background thread, right?
I was developing Really Small Message Broker (RSMB) around the same time, which is single threaded, using multiplexed I/O on the TCP port. At the time, every MQTT server I knew of was multi-threaded – at least one thread for every connecting MQTT client. I thought it would be interesting to see how far you could get with a single thread: reminding me of the techniques we had to use in the 1980s to write games on ZX81s and the like. So, I thought reusing the same approach would be good for the C client – hence only one background thread no matter how many client objects you create (limited to whatever the ‘select’ system call will handle).
Another conscious decision was to use C rather than C++. I started RSMB in C++, but quickly found out that compiler template support was pretty buggy at the time, so dropped back to ANSI standard C. That was somewhat disappointing, but several years later does have the advantage of not being incompatible with Objective-C.
So, which to use when?
- MQTTClient, single-threaded: when you want to use only one thread for your entire application.
- MQTTClient, multi-threaded: when you want ease of use, aren’t bothered about some calls blocking, but still want messages to be sent and received in the background.
- MQTTAsync: when you want no calls to block at all. (Messages will be sent and received on two background threads).
The MQTTAsync API happens to perform better than the MQTTClient API, but that wasn’t the rationale behind it.
Thanks to a Paho contributor, Frank Pagliughi, there is also now a C++ layer over the asynchronous C API. His intent is to have an API which mirrors the corresponding Java one as much as possible.
Hmm, I think we’ve been here before!