If you’re designing an application where devices communicate with a server over a mobile network, there are trade-offs between implementation effort and data transfer. This may not apply to a consumer application, where the application developer doesn’t have to pay the data charges. But if the application is M2M these trade-offs matter.
First, I assume that you want encryption. If you’ve done your risk assessment, and decided to run without encryption, then there’s nothing here for you. The overheads involved in choosing HTTP over a custom protocol, or TCP over UDP, are far smaller.
The easiest technique to implement at both ends is a direct connection to an SSL web server. If you’re using J2ME, this is a standard feature in MIDP 2.0. If you’re programming the device in C, this is simple to handle with libcurl.
This approach is well documented and compatible with a wide range of server frameworks.
The problem with this approach is the SSL handshake. To demonstrate the problem, make a self-signed certificate using openSSL, and then test the handshake:
openssl s_server -accept 9900 -cert host.cert -key host.key
And in another terminal:
openssl s_client -connect localhost:9900
In the s_client results, you’ll see figures like this:
SSL handshake has read 1128 bytes and written 276 bytes
If the application reconnects to the server every five minutes, that can lead to an extra 11MB of data transfer each month. If the application only reconnects every thirty minutes, that still adds 2MB per month.
This overhead can be avoided if you have a mechanism for sharing keys in advance. If the device knows the public key of the server, then the device can open a TCP socket and start sending encrypted data immediately, without any handshake. The upside is saving more than 1kB per connection. The downsides:
- Fewer tools pre-loaded on your platform. For J2ME, you’ll probably need the Bouncy Castle.
- You’ll need to extend your existing server-side toolkit, or implement your own lightweight framework.
- The server will need to both encrypt messages with the device’s public key, and sign them with its own private key.
- You need to get a public key from the device to the server before the server sends its first reply.
Could this be taken further? If the application sends UDP packets to the server, you can drop the setup cost of a TCP connection. This may work for some applications, but there are two problems. First, the packet loss rate on GPRS is far higher than that of the wired Internet. Second, to complicate matters, the remote device is almost certainly behind a NAT gateway. While many gateways will allow two-way UDP sessions, it may be risky to rely on this working in the long term.