Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-35934: Add socket.create_server() utility function #11784

Merged
merged 46 commits into from Apr 8, 2019
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ffa07b3
add socket.bind_socket() function + tests
giampaolo Feb 7, 2019
5618b21
make ftplib use bind_socket() (reuse code)
giampaolo Feb 7, 2019
6b3e634
use bind_socket() in tests (reuse code)
giampaolo Feb 7, 2019
cbaa3c1
set default backlog to 128; provide a more informative message if SO_…
giampaolo Feb 7, 2019
9832435
add 'flags' parameter
giampaolo Feb 7, 2019
17a6b7b
use bind_socket() in more unit-tests
giampaolo Feb 7, 2019
29b1d69
add comment
giampaolo Feb 7, 2019
e4063f2
add NEWS entry
giampaolo Feb 7, 2019
057d831
add 'reuse_addr' arg
giampaolo Feb 8, 2019
b4883cb
rename method
giampaolo Feb 8, 2019
fb0e442
make family and type kw-only args
giampaolo Feb 8, 2019
3e876c5
raise ValueError if type is not SOCK_STREAM/DGRAM
giampaolo Feb 8, 2019
e9fb489
set IPV6_V6ONLY by default
giampaolo Feb 8, 2019
231455f
unittest: check IPV6_V6ONLY is set by default
giampaolo Feb 8, 2019
fbdce4e
fix test failures
giampaolo Feb 11, 2019
2e9e48c
adjust doc wording
giampaolo Feb 12, 2019
4f28c47
change var name
giampaolo Feb 12, 2019
281b914
set flags arg to None by default
giampaolo Feb 12, 2019
e003dfe
document that AF_INET is preferred if host's family is unclear
giampaolo Feb 12, 2019
0a893ca
introduce supports_hybrid_ipv46 and relative bind_socket arg
giampaolo Feb 12, 2019
2d247a2
various improvements:
giampaolo Feb 12, 2019
2c3c85c
update doc
giampaolo Feb 12, 2019
1931e7c
use 'localhost' in tests (safer)
giampaolo Feb 12, 2019
2364a89
raise error on Windows if reuse_addr=True and type != SOCK_DGRAM
giampaolo Feb 13, 2019
1d13a9c
update doc + provide better error message on bind()
giampaolo Feb 13, 2019
46a562e
rename bind_socket() to create_server()
giampaolo Feb 14, 2019
9cd6f01
get rid of reuse_addr arg
giampaolo Feb 14, 2019
d0e69bb
address @vstinner comments
giampaolo Feb 14, 2019
f93058b
fix NameError + add comment clarifying why we in case of ambiguous ho…
giampaolo Feb 14, 2019
63d762e
fix test failures
giampaolo Feb 14, 2019
e95da59
don't use getaddrinfo(), change function signature
giampaolo Feb 14, 2019
22ea974
rename arg hybrid_ipv46 -> dualstack_ipv6
giampaolo Feb 14, 2019
ad8a219
update doc
giampaolo Feb 14, 2019
3b3df83
fix ftplib bug, skip IPV6 tests
giampaolo Feb 15, 2019
d75a600
idlelib/rpc.py: add missing address argument
terryjreedy Feb 15, 2019
265b225
update doc
giampaolo Feb 15, 2019
426907d
fix doc example + remove UDP-related test code which is no longer used
giampaolo Feb 17, 2019
d62499a
merge from master
giampaolo Feb 17, 2019
7b75345
set backlog=0 instead of None; address doc-related review comments
giampaolo Feb 18, 2019
0cf3bb1
change unit-tests so that client does not rely on getaddrinfo() - bet…
giampaolo Feb 18, 2019
12bbf0c
fix wrong client addr + fix travis test due to extra whitespace
giampaolo Feb 18, 2019
caa7605
automatize -> automate
gpshead Feb 19, 2019
ecac919
Merge branch 'master' into bind-socket
giampaolo Mar 6, 2019
f786884
update doc; catch socket.error instead of Exception; remove idlelib i…
giampaolo Mar 6, 2019
e19b28f
Merge branch 'master' into bind-socket
giampaolo Mar 28, 2019
5b49125
update doc (remove ref to activestate recipe)
giampaolo Mar 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
86 changes: 86 additions & 0 deletions Doc/library/socket.rst
Expand Up @@ -595,6 +595,58 @@ The following functions all create :ref:`socket objects <socket-objects>`.
.. versionchanged:: 3.2
*source_address* was added.

.. function:: create_server(address, *, family=AF_INET, backlog=None, reuse_port=False, dualstack_ipv6=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new API in 2019 that defaults to IPv4 without dualstack seems backwards. People will use these defaults without realizing that they're shutting out a big part of the world.

Our defaults should require users to opt-out of dualstack IPv6 and that the dualstack parameter should perhaps be a tri-state rather than a bool: 'no', 'required', 'allow'. the default I'd look for would be allow. such that it would not be an error on a mythical non-dualstack capable host.

When dualstack is enabled, does the family= value have a useful meaning?

On non-dualstack-socket capable hosts (what are those even?) where the user needs a server listening on both IPv4 and IPv6, isn't it true that they need to create two server sockets? create_server() doesn't really have a way to address that case. Supporting such a situation is going to require a has_dualstack_ipv6() conditional and wrangling multiple sockets no matter what.

For a situation where people just want a single "most capable" server socket, your four line conditional code seems like it belongs inside of create_server itself.

Copy link
Contributor Author

@giampaolo giampaolo Feb 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new API in 2019 that defaults to IPv4 without dualstack seems backwards. People will use these defaults without realizing that they're shutting out a big part of the world.

The rationale for having dual-stack disabled by default IMO are 2, consistency and desirableness. In details:

  • not every platform supports dual-stack, so enabling it by default seems inconsistent
  • not all platforms that support it have it enabled by default. E.g. on Linux and FreeBSD it's enabled, on OSX it's not.
  • in case of IPv4 connection, getpeername() will return an IPv4 mapped address like '::ffff:127.0.0.1', which is surprising (more here). To me this is not desirable regardless of how much spread IPv6 adoption is, or even if dual-stack was supported on all platforms. Not all users who want IPv6 necessarily want the dual stack (honestly, initially I was even tempted to exclude this option completely because of all this platform differences - and I'm still happy to take that into consideration BTW).

Also note that asyncio disables dual-stack by default, basically for the same reasons. asyncio case is different though. It does not expose an option to enable dual-stack because it would be useless: it is already able to serve both families with 2 distinct sockets which are handled by the IO loop. We cannot do that here though, unless we use the external recipe I mentioned in the doc (and which should not end up in socket.py IMO).

Our defaults should require users to opt-out of dualstack IPv6 and that the dualstack parameter should perhaps be a tri-state rather than a bool: 'no', 'required', 'allow'. the default I'd look for would be allow. such that it would not be an error on a mythical non-dualstack capable host.

I hear you. I also considered that, but I couldn't come up with an API which made sense. Basically that's why the API evolved into being "explicit" by forcing you to specify both family and dualstack_ipv6.

On non-dualstack-socket capable hosts (what are those even?)

Windows does not support dual-stack. Linux, OSX and FreeBSD do. I updated the doc adding:
"Most POSIX platforms are supposed to support this option."

When dualstack is enabled, does the family= value have a useful meaning?

As this currently stands, family has to be explicitly set to AF_INET6. One may argue that should be implicit if dualstack_ipv6=True. As of now I'm more inclined to think it should be set explicitly because:

  • it helps clarifying that you're primarily dealing with an IPv6 socket, even if it has mixed capabilities.
  • it reflects the fact that socket.socket() default family is AF_INET, so the same way you do socket.socket(AF_INET6) you should do socket.create_server(addr, family=AF_INET6).

But I agree this is indeed debatable and I have mixed feelings about it.

On non-dualstack-socket capable hosts (what are those even?) where the user needs a server listening on both IPv4 and IPv6, isn't it true that they need to create two server sockets? create_server() doesn't really have a way to address that case.

Correct. If dual-stack is not supported natively by the kernel you have to create 2 sockets. The ActiveState recipe I mentioned in the doc includes a class which does that. The reason for not including it in socket.py is because the API is non-obvious / incompatible. E.g. fileno(), detach(), family and possibly others wouldn't know what to return.


Convenience function which creates a :data:`SOCK_STREAM` type socket
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you don't just say it creates a TCP socket? I think this is guaranteed by Posix for AF_INET and AF_INET6 with SOCK_STREAM and proto set to zero.

bound to *address* (a 2-tuple ``(host, port)``) and return the socket
object.

*family* should be either :data:`AF_INET` or :data:`AF_INET6`.
*backlog* is the queue size passed to :meth:`socket.listen`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe what backlog=None means.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Updated doc (including your suggestion of making it default to 0 instead of None):

   *backlog* is the queue size passed to :meth:`socket.listen`; when ``0``
   a default reasonable value is chosen.

*reuse_port* dictates whether to set :data:`SO_REUSEPORT` socket option.

If *dualstack_ipv6* is true and the platform supports it the socket will
gpshead marked this conversation as resolved.
Show resolved Hide resolved
be able to accept both IPv4 and IPv6 connections.
In this case the address returned by :meth:`socket.getpeername` when an IPv4
connection occurs will be an IPv6 address represented as an IPv4-mapped IPv6
address like ``":ffff:127.0.0.1"``.
If *dualstack_ipv6* is false it will explicitly disable this functionality
on platforms that enable it by default (e.g. Linux).
For platforms not supporting this functionality natively you could use this
`MultipleSocketsListener recipe <http://code.activestate.com/recipes/578504/>`__.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use an https link. (also, activestate appears to be down or DOSed right now)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Done.

This parameter can be used in conjunction with :func:`has_dualstack_ipv6`.

Here's an echo server example listening on all interfaces, port 8888,
accepting both IPv4 and IPv6 connections (if supported):

::

import socket

with socket.create_server(("", 8888),
dualstack_ipv6=socket.has_dualstack_ipv6()) as server:
conn, addr = server.accept()
with conn:
while True:
data = conn.recv(1024)
if not data:
break
conn.send(data)

.. note::
On POSIX :data:`SO_REUSEADDR` socket option is set in order to immediately
reuse previous sockets which were bound on the same *address* and remained
in TIME_WAIT state.

.. versionadded:: 3.8

.. function:: has_dualstack_ipv6()

Return ``True`` if the platform supports creating a :data:`SOCK_STREAM`
socket which can handle both :data:`AF_INET` or :data:`AF_INET6`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe how one creates such a socket when this returns True given that the socket() call only accepts a single family.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already described in create_function which is right above (and ends with a code sample). I don't think it's worth repeating the description of the behavior (or showing the same code sample).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was assuming someone will want to use this in combination with plain socket() calls without create_socket() at times. ie: Should we mention the setsockopt IPV6_V6ONLY 0 dance for people not using create_socket? Or just leave that as one for the networking books?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd leave it out as a low-level detail. As of now, the only thing that the doc mentions is the existence of IPV6_* constants. We may decide to improve that as a separate doc fix though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think AF_INET and AF_INET6 are mutually exclusive for a given socket. Perhaps it is more accurate to say the socket can handle both IP v4 and v6.

(IPv4 / IPv6) connections.

.. versionadded:: 3.8

.. function:: fromfd(fd, family, type, proto=0)

Expand Down Expand Up @@ -1779,6 +1831,40 @@ sends traffic to the first one connected successfully. ::
print('Received', repr(data))


The two examples above can be rewritten by using :meth:`socket.create_server`
and :meth:`socket.create_connection` convenience functions.
If the platform supports it, :meth:`socket.create_server` has the extra
advantage of creating an agnostic IPv4/IPv6 server:

::

# Echo server program
import socket

HOST = None
PORT = 50007
s = socket.create_server((HOST, PORT), dualstack_ipv6=socket.has_dualstack_ipv6())
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.send(data)

::

# Echo client program
import socket

HOST = 'daring.cwi.nl'
PORT = 50007
with socket.create_connection((HOST, PORT)) as s:
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))


The next example shows how to write a very simple network sniffer with raw
sockets on Windows. The example requires administrator privileges to modify
the interface::
Expand Down
9 changes: 9 additions & 0 deletions Doc/whatsnew/3.8.rst
Expand Up @@ -214,6 +214,15 @@ contain characters unrepresentable at the OS level.
(Contributed by Serhiy Storchaka in :issue:`33721`.)


socket
------

Added :meth:`~socket.create_server()` and :meth:`~socket.has_dualstack_ipv6()`
convenience functions to automatize the necessary tasks usually involved when
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may name tasks:

Suggested change
convenience functions to automatize the necessary tasks usually involved when
convenience functions to automatize the necessary tasks (bind, listen) usually involved when

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"automatize" isn't a word. :) I'd suggest "to automate" or "that encapsulate" perhaps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

False friend betrayed me. =)
Fixed.

creating a server socket, including accepting both IPv4 and IPv6 connections
on the same socket. (Contributed by Giampaolo Rodola in :issue:`17561`.)


shutil
------

Expand Down
21 changes: 1 addition & 20 deletions Lib/ftplib.py
Expand Up @@ -302,26 +302,7 @@ def sendeprt(self, host, port):

def makeport(self):
'''Create a new socket and send a PORT command for it.'''
err = None
sock = None
for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
af, socktype, proto, canonname, sa = res
try:
sock = socket.socket(af, socktype, proto)
sock.bind(sa)
except OSError as _:
err = _
if sock:
sock.close()
sock = None
continue
break
if sock is None:
if err is not None:
raise err
else:
raise OSError("getaddrinfo returns an empty list")
sock.listen(1)
sock = socket.create_server(("", 0), family=self.af, backlog=1)
port = sock.getsockname()[1] # Get proper port
host = self.sock.getsockname()[0] # Get proper host
if self.af == socket.AF_INET:
Expand Down
5 changes: 2 additions & 3 deletions Lib/idlelib/rpc.py
Expand Up @@ -530,9 +530,8 @@ class RPCClient(SocketIO):
nextseq = 1 # Requests coming from the client are odd numbered

def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM):
self.listening_sock = socket.socket(family, type)
self.listening_sock.bind(address)
self.listening_sock.listen(1)
self.listening_sock = socket.create_server(
address, family=family, type=type, backlog=1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is type a valid keyword? If not, maybe this needs a test case :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch! I missed that, thanks. I just removed this part and left idlelib alone in f786884. I will probably get back at this in a separate PR because it's more controversial.


def accept(self):
working_sock, address = self.listening_sock.accept()
Expand Down
91 changes: 89 additions & 2 deletions Lib/socket.py
Expand Up @@ -60,8 +60,8 @@
EAGAIN = getattr(errno, 'EAGAIN', 11)
EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)

__all__ = ["fromfd", "getfqdn", "create_connection",
"AddressFamily", "SocketKind"]
__all__ = ["fromfd", "getfqdn", "create_connection", "create_server",
"has_dualstack_ipv6", "AddressFamily", "SocketKind"]
__all__.extend(os._get_exports_list(_socket))

# Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for
Expand Down Expand Up @@ -728,6 +728,93 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
else:
raise error("getaddrinfo returns an empty list")


def has_dualstack_ipv6():
"""Return True if the platform supports creating a SOCK_STREAM socket
which can handle both AF_INET and AF_INET6 (IPv4 / IPv6) connections.
"""
if not has_ipv6 \
or not hasattr(_socket, 'IPPROTO_IPV6') \
or not hasattr(_socket, 'IPV6_V6ONLY'):
return False
try:
with socket(AF_INET6, SOCK_STREAM) as sock:
gpshead marked this conversation as resolved.
Show resolved Hide resolved
sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 0)
return True
except error:
return False


def create_server(address, *, family=AF_INET, backlog=None, reuse_port=False,
dualstack_ipv6=False):
"""Convenience function which creates a SOCK_STREAM type socket
bound to *address* (a 2-tuple (host, port)) and return the socket
object.

*family* should be either AF_INET or AF_INET6.
*backlog* is the queue size passed to socket.listen().
*reuse_port* dictate whether to use the SO_REUSEPORT socket option.
*dualstack_ipv6*: if true and the platform supports it, it will
create a socket able to accept both IPv4 and IPv6 connections.
When false it will explicitly disable this option on platforms
that enable it by default (e.g. Linux).

>>> with create_server((None, 8000)) as server:
... while True:
... conn, addr = server.accept()
... # handle new connection
"""
if reuse_port and not hasattr(_socket, "SO_REUSEPORT"):
raise ValueError("SO_REUSEPORT not supported on this platform")
if dualstack_ipv6:
if not has_dualstack_ipv6():
raise ValueError("dualstack_ipv6 not supported on this platform")
if family != AF_INET6:
raise ValueError("dualstack_ipv6 requires AF_INET6 family")
gpshead marked this conversation as resolved.
Show resolved Hide resolved
sock = socket(family, SOCK_STREAM)
try:
# Note about Windows. We don't set SO_REUSEADDR because:
# 1) It's unnecessary: bind() will succeed even in case of a
# previous closed socket on the same address and still in
# TIME_WAIT state.
# 2) If set, another socket will be free to bind() on the same
# address, effectively preventing this one from accepting
# connections. Also, it may set the process in a state where
# it'll no longer respond to any signals or graceful kills.
# See: msdn2.microsoft.com/en-us/library/ms740621(VS.85).aspx
if os.name not in ('nt', 'cygwin') and \
hasattr(_socket, 'SO_REUSEADDR'):
try:
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
except error:
# Fail later on bind(), for platforms which may not
# support this option.
pass
if reuse_port:
sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
if has_ipv6 and family == AF_INET6:
if dualstack_ipv6:
sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 0)
elif hasattr(_socket, "IPV6_V6ONLY") and \
hasattr(_socket, "IPPROTO_IPV6"):
# Disable IPv4/IPv6 dual stack support (enabled by
# default on Linux) which makes a single socket
# listen on both address families in order to
# eliminate cross-platform differences.
sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 1)
try:
sock.bind(address)
except error as err:
err_msg = '%s (while attempting to bind on address %r)' % \
(err.strerror, address)
raise error(err.errno, err_msg) from None
sock.listen(backlog or 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just set the backlog default value to 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that makes sense. Done.

return sock
except Exception:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use plain except to catch all exceptions (e.g. KeyboardInterrupt could be raised during a slow DNS lookup)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I think it's saner to just catch socket.error, the same way it's done in create_connection(). Changed it in f786884.

sock.close()
raise


def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""Resolve host and port into list of address info entries.

Expand Down
8 changes: 2 additions & 6 deletions Lib/test/_test_multiprocessing.py
Expand Up @@ -3323,9 +3323,7 @@ def _listener(cls, conn, families):
new_conn.close()
l.close()

l = socket.socket()
l.bind((test.support.HOST, 0))
l.listen()
l = socket.create_server((test.support.HOST, 0))
conn.send(l.getsockname())
new_conn, addr = l.accept()
conn.send(new_conn)
Expand Down Expand Up @@ -4077,9 +4075,7 @@ def _child_test_wait_socket(cls, address, slow):

def test_wait_socket(self, slow=False):
from multiprocessing.connection import wait
l = socket.socket()
l.bind((test.support.HOST, 0))
l.listen()
l = socket.create_server((test.support.HOST, 0))
addr = l.getsockname()
readers = []
procs = []
Expand Down
5 changes: 1 addition & 4 deletions Lib/test/eintrdata/eintr_tester.py
Expand Up @@ -284,12 +284,9 @@ def test_sendmsg(self):
self._test_send(lambda sock, data: sock.sendmsg([data]))

def test_accept(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = socket.create_server((support.HOST, 0))
self.addCleanup(sock.close)

sock.bind((support.HOST, 0))
port = sock.getsockname()[1]
sock.listen()

code = '\n'.join((
'import socket, time',
Expand Down
10 changes: 1 addition & 9 deletions Lib/test/test_asyncio/functional.py
Expand Up @@ -60,21 +60,13 @@ def tcp_server(self, server_prog, *,
else:
addr = ('127.0.0.1', 0)

sock = socket.socket(family, socket.SOCK_STREAM)

sock = socket.create_server(addr, family=family, backlog=backlog)
if timeout is None:
raise RuntimeError('timeout is required')
if timeout <= 0:
raise RuntimeError('only blocking sockets are supported')
sock.settimeout(timeout)

try:
sock.bind(addr)
sock.listen(backlog)
except OSError as ex:
sock.close()
raise ex

return TestThreadedServer(
self, sock, server_prog, timeout, max_clients)

Expand Down
12 changes: 3 additions & 9 deletions Lib/test/test_asyncio/test_events.py
Expand Up @@ -667,9 +667,7 @@ def data_received(self, data):
super().data_received(data)
self.transport.write(expected_response)

lsock = socket.socket()
lsock.bind(('127.0.0.1', 0))
lsock.listen(1)
lsock = socket.create_server(('127.0.0.1', 0), backlog=1)
addr = lsock.getsockname()

message = b'test data'
Expand Down Expand Up @@ -1118,9 +1116,7 @@ def connection_made(self, transport):
super().connection_made(transport)
proto.set_result(self)

sock_ob = socket.socket(type=socket.SOCK_STREAM)
sock_ob.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_ob.bind(('0.0.0.0', 0))
sock_ob = socket.create_server(('0.0.0.0', 0))

f = self.loop.create_server(TestMyProto, sock=sock_ob)
server = self.loop.run_until_complete(f)
Expand All @@ -1136,9 +1132,7 @@ def connection_made(self, transport):
server.close()

def test_create_server_addr_in_use(self):
sock_ob = socket.socket(type=socket.SOCK_STREAM)
sock_ob.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_ob.bind(('0.0.0.0', 0))
sock_ob = socket.create_server(('0.0.0.0', 0))

f = self.loop.create_server(MyProto, sock=sock_ob)
server = self.loop.run_until_complete(f)
Expand Down
11 changes: 3 additions & 8 deletions Lib/test/test_asyncio/test_streams.py
Expand Up @@ -592,8 +592,7 @@ async def handle_client(self, client_reader, client_writer):
await client_writer.wait_closed()

def start(self):
sock = socket.socket()
sock.bind(('127.0.0.1', 0))
sock = socket.create_server(('127.0.0.1', 0))
self.server = self.loop.run_until_complete(
asyncio.start_server(self.handle_client,
sock=sock,
Expand All @@ -605,8 +604,7 @@ def handle_client_callback(self, client_reader, client_writer):
client_writer))

def start_callback(self):
sock = socket.socket()
sock.bind(('127.0.0.1', 0))
sock = socket.create_server(('127.0.0.1', 0))
addr = sock.getsockname()
sock.close()
self.server = self.loop.run_until_complete(
Expand Down Expand Up @@ -796,10 +794,7 @@ def test_drain_raises(self):

def server():
# Runs in a separate thread.
sock = socket.socket()
with sock:
sock.bind(('localhost', 0))
sock.listen(1)
with socket.create_server(('localhost', 0)) as sock:
addr = sock.getsockname()
q.put(addr)
clt, _ = sock.accept()
Expand Down
4 changes: 1 addition & 3 deletions Lib/test/test_epoll.py
Expand Up @@ -41,9 +41,7 @@
class TestEPoll(unittest.TestCase):

def setUp(self):
self.serverSocket = socket.socket()
self.serverSocket.bind(('127.0.0.1', 0))
self.serverSocket.listen()
self.serverSocket = socket.create_server(('127.0.0.1', 0))
self.connections = [self.serverSocket]

def tearDown(self):
Expand Down