Wednesday, November 7, 2012

UDP or TCP for lossy networks?

So I was discussing video streams today and how typical video streaming protocols like RTP react to loss on the network -- i.e, by dropping frames -- and someone made the statement, "TCP would be better for lossy networks." He was wrong, of course. But I hear you saying, "but... but... TCP recovers from data loss!" Well, yes... if you don't care about timing or throughput, only about reliability. But if you're talking video streaming, TCP could result in loss of not only a few frames, but could result in loss of seconds worth of frames, or even cause video cameras, switches, or servers to crash.

At which point you're saying, "say wha?!" But here's the deal. If you lose a video packet with UDP, you lose a frame. RTP handles reassembling the packets into frames, if the next frame has come in and there's no packet to fill in slot X in the previous frame, RTP just throws the frame away. If you're getting 28 frames per second, you lose one frame out of that, big deal. Just replay the previous frame on replay, nobody will notice.

Now let's say you're using TCP. A missing packet occurs. TCP is expecting packet N... and doesn't get it. The TCP window goes SLAM at that point -- 4 megabytes of data backs up behind the missing packet as TCP tries to build its window and has a missing piece that it is waiting for, then TCP flow control assures that no more data is accepted until after the 1.5 second timeout causes a retransmit on the sender side. What this does is add 1.5 seconds worth of delay. You have a 1.5 seconds of delay, 4 megabyte window, and a gigabit Ethernet line, and what that means is that one lost packet every 1.5 seconds basically causes your gigabit Ethernet line to become a 21 megabit/sec Ethernet line. Congratulations, you just returned to 1985. And if you have 200 megabits/sec of incoming data, all that data is piled up in the network stack somewhere between you and the cameras, and you're in big trouble.

For streaming data, UDP thus handles a lossy network much more gracefully than TCP does. At least, that's true if you don't care about data loss due to redundancy in the data stream. I.e., frame 1000 in a video stream is very similar to frame 999 and frame 1001, so if frame 1000 goes missing it can be recontructed as simply the duplicate of the preceding or following frame. So what if you *do* care about data loss?

The reality is that if you *do* care about data loss, you're much more likely to get good results when streaming data if you use out-of-band data recovery. That is, if you've tried filling your frame, you already have packets for a couple more frames incoming, and you're missing a couple of packets, request packet retransmission directly via a NAK rather than wait for the sender to timeout waiting for an ACK. Thus *one* reason why most reliable multicast protocols rely on recipients proactively sending a NAK rather than time out waiting for an ACK before sending a packet. You can combine the two if you wish -- in this case, ACK would let the sender know that all packets in the frame were received thus it doesn't need to retain the frame in order to potentially service a NAK -- if you're really wanting both reliability and performance. But TCP doesn't do that. Which is why, on a lossy network, TCP is probably the worst protocol you could use for streaming data, and why the person who said "TCP is best for lossy networks" was wrong, at least for this application.


No comments:

Post a Comment