family = socket.AF_INET
if flags is None:
flags = socket.AI_PASSIVE
+ bound_port = None
for res in set(socket.getaddrinfo(address, port, family, socket.SOCK_STREAM,
0, flags)):
af, socktype, proto, canonname, sockaddr = res
# Python 2.x on windows doesn't have IPPROTO_IPV6.
if hasattr(socket, "IPPROTO_IPV6"):
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
+
+ # automatic port allocation with port=None
+ # should bind on the same port on IPv4 and IPv6
+ host, requested_port = sockaddr[:2]
+ if requested_port == 0 and bound_port is not None:
+ sockaddr = tuple([host, bound_port] + list(sockaddr[2:]))
+
sock.setblocking(0)
sock.bind(sockaddr)
+ bound_port = sock.getsockname()[1]
sock.listen(backlog)
sockets.append(sock)
return sockets
import sys
import time
-from tornado.netutil import BlockingResolver, ThreadedResolver, is_valid_ip
+from tornado.netutil import BlockingResolver, ThreadedResolver, is_valid_ip, bind_sockets
from tornado.stack_context import ExceptionStackContext
from tornado.testing import AsyncTestCase, gen_test
from tornado.test.util import unittest
self.assertTrue(not is_valid_ip(' '))
self.assertTrue(not is_valid_ip('\n'))
self.assertTrue(not is_valid_ip('\x00'))
+
+
+class TestPortAllocation(unittest.TestCase):
+ def test_same_port_allocation(self):
+ sockets = bind_sockets(None, 'localhost')
+ port = sockets[0].getsockname()[1]
+ self.assertTrue(all(s.getsockname()[1] == port for s in sockets[1:]))