Skip to main content

Lib/socket.py

Source:

cpython 3.14 @ ab2d84fe1023/Lib/socket.py

Lib/socket.py is the pure-Python layer that sits on top of the _socket C extension. It re-exports the AF_* and SOCK_* constants, wraps the raw _socket.socket type in a subclass that adds buffered I/O and context-manager support, and provides several convenience factory functions for common connection patterns.

Map

LinesSymbolPurpose
1-100module header, importsPull in _socket, os, io, selectors; re-export constants
~100-250socket classSubclass of _socket.socket; adds makefile(), __enter__/__exit__, sendfile()
~250-320socket.makefile()Returns a buffered SocketIO wrapper around the socket fd
~320-430create_connection()getaddrinfo loop with optional source address and timeout
~430-530create_server()Binds and listens; sets SO_REUSEADDR and optionally SO_REUSEPORT
~530-560setdefaulttimeout() / getdefaulttimeout()Module-level timeout forwarded to _socket
~560-900constant re-exports, has_dualstack_ipv6(), fromfd(), helper guardsCompatibility surface and platform probes

Reading

socket class and makefile()

The socket class in Lib/socket.py subclasses _socket.socket to add a makefile() method. The C type provides raw send/recv; makefile() layers Python io buffering on top so callers can treat a socket like a file object. The returned object is a SocketIO instance wrapped in BufferedReader, BufferedWriter, or BufferedRWPair depending on the requested mode.

# CPython: Lib/socket.py:239 socket.makefile
def makefile(self, mode="r", buffering=None, *,
encoding=None, errors=None, newline=None):
"""makefile(...) -> an I/O stream connected to the socket"""
writing = "w" in mode
reading = "r" in mode or not writing
assert reading or writing
raw = SocketIO(self, mode)
...

The SocketIO object holds a reference to the socket so that the socket's reference count stays positive for the lifetime of the file-like object. Closing the file does not close the socket; the caller must close the socket separately.

create_connection() and getaddrinfo loop

create_connection() is the recommended way to open a client TCP socket. It calls getaddrinfo() to resolve the host and port into a list of (family, type, proto, canonname, sockaddr) tuples and then tries each in turn, closing failed sockets before moving on. This makes it transparently dual-stack: if the host has both A and AAAA records, it will try the IPv6 address first (subject to OS ordering) and fall back to IPv4.

# CPython: Lib/socket.py:330 create_connection
def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
source_address=None, *, all_errors=False):
host, port = address
exceptions = []
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket(af, socktype, proto)
if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
sock.connect(sa)
exceptions.clear()
return sock
except error as exc:
...

The all_errors keyword (added in 3.11) controls whether all exceptions are aggregated into an ExceptionGroup or only the last one is raised.

create_server() and socket options

create_server() is a factory for server-side sockets. It always sets SO_REUSEADDR on POSIX systems to allow rebinding after a crash. When reuse_port=True is requested it additionally sets SO_REUSEPORT, which lets multiple processes bind the same port for load distribution. On Windows neither option is set in the same way because the platform semantics differ.

# CPython: Lib/socket.py:454 create_server
def create_server(address, *, family=AF_INET, backlog=None,
reuse_port=False, dualstack_ipv6=False):
...
sock = socket(family, SOCK_STREAM)
try:
if os.name not in ('nt', 'cygwin') and \
hasattr(_socket, 'SO_REUSEADDR'):
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
if reuse_port:
sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
...

gopy notes

Status: not yet ported.

Planned package path: module/socket/.

The C extension _socket would need to be ported first as a Go package that wraps the OS networking syscalls. The pure-Python layer in Lib/socket.py would then be either re-implemented in Go or loaded from the stdlib snapshot. The makefile() buffering logic maps naturally onto Go's bufio package. The create_connection() loop corresponds closely to net.Dial with a custom resolver, though the fallback-per-address behavior would need explicit implementation. create_server() maps to net.Listen plus syscall.SetsockoptInt calls for SO_REUSEADDR and SO_REUSEPORT.