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

Phil Mayers p.mayers at imperial.ac.uk
Sat Apr 23 02:52:35 MDT 2016


On 23/04/16 03:36, Jonathan Vanasco wrote:
> Thanks for all this.
>
> A few quick notes:
>
> On Apr 20, 2016, at 9:15 PM, Glyph wrote:
>
>> 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 only
>> calls "bind()" from sock_bind, not from send(), nor does
>> https://github.com/python/cpython/blob/master/Lib/socket.py engage in
>> any such shenanigans.
>
> The 'feature' of Python is a few things:
>
>  From what I could tell, the actual communication and binding happens
> somewhere in the c module.
>

Not so. It's down inside the kernel. All applications using the socket 
API in this way will display this behaviour, regardless of language.

Seriously, try it and see:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
	int s,r;
	struct sockaddr_in dst;
	dst.sin_family = AF_INET;
	dst.sin_port = htons(37);
	dst.sin_addr.s_addr = INADDR_LOOPBACK;

	s = socket(AF_INET, SOCK_DGRAM, 0);
	printf("socket created\n");
	sleep(30);
	sendto(s, "foo", 3, 0, &dst, sizeof(dst));
	printf("socket used\n");
	sleep(30);
	return 0;
}

Compile & run the program and quickly lsof the process, you'll see:

test    16258 pjm3    3u  sock    0,8      0t0 87111053 protocol: UDP

...wait until it has printed that it has used the socket, repeat and 
you'll see:

test    16258 pjm3    3u  IPv4 87111053      0t0     UDP *:51669

As glyph says, this is an inherent feature of the socket API. When you 
create a socket, it is unbound because you might be about to call bind() 
yourself.

If you then use it without binding it, the kernel has to allocate a 
source port, and in turn an interface, and the only sensible choice 
absent any instructions from userland is INADDR_ANY.

This is definitely not Python doing this.




More information about the Twisted-Python mailing list