[Twisted-Python] UDP vs TCP for bittorrent-style file transfer

glyph at divmod.com glyph at divmod.com
Mon Sep 22 12:24:52 MDT 2008


On 01:06 am, tiredashell at gmail.com wrote:
>>It's not easier to get UDP through NATs.  It's just as hard or harder.
>
>It must be a widely held error, then, because it's what I hear every 
>time
>the subject arises. My understanding was that since UDP doesn't have 
>the
>concept of "streams," most NATs will allow all UDP packets through to a
>given port one it is first hole-punched.

If you are a piece of software behind a NAT, and you want to accept a 
connection from a peer, there are three things you can do:

  1. Require some explicit configuration from the user; ask them to punch 
a hole through their NAT and tell you what port to use.  This is by far 
the easiest for you, but considered unacceptable since its default 
configuration will usually be broken.
  2. Use a protocol like UPnP or Nat-PMP to get around the user's router. 
This will work on a minority of deployed endpoints, but when it does 
work it will work great, and your application can just make regular TCP 
connections.
  3. Punch a hole, abusing the router's NAT routing rules in order to get 
it to think it's making a connection when it is actually accepting one. 
There are about six different ways to do this, but you can do it with 
UDP *or* TCP.  Different routers support different schemes, and I don't 
just mean "some support TCP, some support UDP": UDP port mapping 
_usually_ works a certain way, but there are exceptions.  You should at 
least read the papers referenced here:  http://midcom- 
p2p.sourceforge.net/

In order to build a truly robust application you will need to do all of 
the above.  Even if you do #2 and #3 perfectly, there are a surprising 
percentage of home routers (say, 5-10%) which are just buggy and won't 
route your traffic properly to another NAT no matter what you do, so you 
always need to provide a "just tell the NAT what to do manually" option. 
(Or, forward your traffic through some known-to-work intermediary.)
>Nat traversal aside, I'm also concerned about performance, and since 
>TCP
>doesn't make in-order delivery optional, I'm still tempted to stick 
>with
>UDP...

TCP will, in general, "perform" better than UDP, because TCP can cheat 
whereas UDP can't.  Your ISP can (and probably does, according to rumors 
I've heard from people who have worked on such things) deploy "smart" 
routers which can prioritize traffic using the additional information 
present in TCP headers which UDP doesn't provide.  Plus, there are 
things that your operating system is doing (as James already mentioned) 
that are extensions to the core TCP spec.

If you don't understand _at least_ enough about TCP to have implemented 
it yourself once, then you probably don't understand enough to make the 
decision to use UDP for performance reasons.  I am saying this because 
it was at the point where I actually implemented TCP myself that I 
gained this insight :).

I started a project a while ago to try to abstract away all this NAT- 
traversal nonsense and present an API for making a connection to a peer- 
to-peer user over whatever methods are available.  It's definitely in 
need of some maintenance, but if you're already using Twisted I think 
you'll find it easier to get started with this than to build your own 
P2P framework from the ground up: 
http://divmod.org/trac/wiki/DivmodVertex

Good luck!




More information about the Twisted-Python mailing list