> On Apr 20, 2016, at 3:42 PM, Jonathan Vanasco <twisted-pyt...@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
_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Reply via email to