[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