[Twisted-Python] twisted listening on UDP port, why?

Glyph glyph at twistedmatrix.com
Wed Apr 20 19:15:55 MDT 2016


> On Apr 20, 2016, at 3:42 PM, Jonathan Vanasco <twisted-python at 2xlp.com> wrote:
> 
> 
> On Apr 20, 2016, at 1:31 PM, Jonathan Vanasco wrote:
> 
>> A specific library was keeping the port open.  I'm tracking down how/why right now.
> 
> So this was fun <sarcasm> thing to learn...
> 
> An undocumented (yay) feature of python appears to be... python binds to a random port on all interfaces (0.0.0.0) once you send UDP data through it.  I assume this is to allow for a response to come back.  

This isn't so much a feature of Python as it is a feature of the BSD sockets API.  Sending traffic through a socket, whether it's TCP or UDP, has to bind a client port.  Given the nature of UDP, binding on all interfaces is the expectation unless you specify.

I didn't have time to test a simple C program before sending this message, but https://github.com/python/cpython/blob/master/Modules/socketmodule.c <https://github.com/python/cpython/blob/master/Modules/socketmodule.c> only calls "bind()" from sock_bind, not from send(), nor does https://github.com/python/cpython/blob/master/Lib/socket.py <https://github.com/python/cpython/blob/master/Lib/socket.py> engage in any such shenanigans.

> We're using statsd for metrics in our twisted daemon and detect issues post-deployment.
> 
> If you haven't used it, it's a node.js daemon from etsy that collects udp data and pipes it into python's graphite/carbon libraries.  Then you get fancy graphics.

There's also a Twisted version :) https://pypi.python.org/pypi/txStatsD <https://pypi.python.org/pypi/txStatsD>

txStatsD contains both server and client, so maybe you want to use that client if you want better control over the UDP port.

>    # this does nothing...
>    sock = socket.socket(family, socket.SOCK_DGRAM)
>    # but this binds to 0.0.0.0
>    sock.sendto(data.encode('ascii'), addr)
> 
> Sending data to the stats collector on 127.0.0.1:8125 inherently made python bind to 0.0.0.0, and on a port that seems to be in the 40000-60000 range.  

That range is the ephemeral client port range <https://en.wikipedia.org/wiki/Ephemeral_port <https://en.wikipedia.org/wiki/Ephemeral_port>> so that's what would be expected of an implicitly-bound socket.

> Since a socket to the stats collector is only created once for the process, Python holds that open the entire time.

If it needs to send UDP traffic, it needs to be able to receive UDP traffic as well.  You can bind it to a more specific interface, but you can't prevent the port from opening to receive traffic.

-glyph
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20160420/bdc599e3/attachment-0002.html>


More information about the Twisted-Python mailing list