Search code examples
tcpudpwifiandroid-wifibattery

Using UDP versus TCP for Wi-Fi comm - battery drain?


I have several questions, but SO's practice is not to ask multiple at once, so i'll put the same intro and number them in logical order.

I'm writing a business app that communicates with a .NET Win-service. Target audience are staff, working in a building with Wi-Fi coverage. The app is used for announcement of certain events that eventually will require receiver's acceptance or rejection (so transmission must be bi-directional).

I have implemented device registration over TCP, followed by a switch to a UDP data channel. Architecturally, there is a startup Application class (necessary to configure some global settings), which in turn opens the LogIn activity, which opens the Main activity upon successful registration. As it starts, Main launches a foreground service (CommSvc), which starts the UDP-comm thread.

I'm developing in VisualStudio 2017 15.5.4, Xamarin 4.8.0.757, Xamarin.Android SDK - 8.1.3.0.
My test devices are 2 phones LG Nexus 4 (Android 4.3, API 18), BLU Vivo 5 Mini (6.0, 23),
and a Samsung SM-T377V (6.0.1, 23) tablet, which i'm thinking about upgrading to 7.0.


Q1. It has been estimated by our in-house network engineers that utilizing TCP will result in mobile radio draining the battery faster (vs. UDP). Is that so indeed?

TCP gives guaranteed ordered delivery of the byte-stream (provided the device stays in range). UDP packets may get lost, thus requiring some kind of ACK-and-retransmit-on-failure protocol.

Due to Wi-Fi nature of the channel there can never be a guarantee that a sent packet reached the target device (e.g. it went out of range), therefore an ACK-and-retransmit protocol becomes necessary no matter what, am i right? (There are liability aspects)


Solution

  • Since TCP has to do more sending and receiving to ensure packet delivery, it uses more traffic and more wifi time, thus more battery.

    If you want guaranteed delivery, you either use TCP, or build an analog of it on top of UDP, likely a less efficient one.

    If you don't want guaranteed delivery, e.g. you post data that quickly become obsolete, and don't mind losing some of the intermediate values, then UDP is a way to go.

    If the data you send are of considerable size, I suppose compressing them before transmission, and decompressing on reception, will save more power in radio than consume in CPU.

    Not getting an ACK timely from receiver must be an error in a TCP stream, likely signaled via an IOException, so you can detect incomplete communications. This does not tell you if what you have sent has reached the destination, though. Your server should be prepared to check for communication failures, and likely be ready to re-receive (and discard) a command it has already received and executed recently. Sequence numbers, TCP-style, help on this level, too. OTOH if the device always asks the server about the status after a re-connection, and the server reminds about the last accepted command, this is not needed.

    In the above situation TCP is still useful if your payloads are large enough, and you don't want to re-implement the fragmentaton / ooo-reception / restoration logic. For guaranteed very small payloads (under 1kb, I'd say) the smallest commonly used IP packet is large enough, so you can re-implement the rather simple syn-ack logic on the app level.

    Normally a socket with a pretty long value (tens or hundreds of seconds) would work well when connectivity is unstable (e.g. poor wi-fi reception). Be sure to .SetSoTimeout(something_reasonable), though; the default is infinite!