Skip to main content

Modules/socketmodule.c (part 2)

Source:

cpython 3.14 @ ab2d84fe1023/Modules/socketmodule.c

This annotation covers advanced socket methods and I/O. See modules_socket_detail for socket.__init__, bind, connect, accept, send, recv, and close.

Map

LinesSymbolRole
1-80socket.recv_intoReceive into a writable buffer (zero-copy)
81-200socket.sendmsg / socket.recvmsgScatter-gather I/O with ancillary data
201-340socket.makefileWrap socket in a file-like object
341-480socket.setblocking / socket.settimeoutNon-blocking and timeout modes
481-620socket.getaddrinfoResolve hostname + port to address tuples
621-1000SSL integrationssl.wrap_socket and TLS context support

Reading

socket.recv_into

// CPython: Modules/socketmodule.c:3280 sock_recv_into
static PyObject *
sock_recv_into(PySocketSockObject *s, PyObject *args)
{
Py_buffer buf;
Py_ssize_t recvlen = 0;
int flags = 0;
/* Get a writable buffer view */
if (!PyArg_ParseTuple(args, "w*|ni:recv_into", &buf, &recvlen, &flags))
return NULL;
if (recvlen < 0 || recvlen > buf.len)
recvlen = buf.len;
/* recv directly into the buffer */
Py_ssize_t n = sock_recv_guts(s, buf.buf, recvlen, flags);
PyBuffer_Release(&buf);
if (n < 0) return NULL;
return PyLong_FromSsize_t(n);
}

socket.recv_into(ba) reads directly into a bytearray or any writable buffer without a temporary bytes allocation. Returns the number of bytes received.

socket.sendmsg

// CPython: Modules/socketmodule.c:3480 sock_sendmsg
/* sendmsg(buffers, ancdata=[], flags=0, address=None)
buffers -- sequence of bytes-like objects (scatter-gather)
ancdata -- sequence of (cmsg_level, cmsg_type, data) tuples
address -- destination for UDP sockets
*/

sendmsg uses writev-style scatter-gather I/O. Ancillary data carries out-of-band information like file descriptors (SCM_RIGHTS), process credentials, or timestamp requests.

socket.makefile

// CPython: Lib/socket.py:240 makefile (Python wrapper)
def makefile(self, mode='r', buffering=None, *,
encoding=None, errors=None, newline=None):
"""Return a file object associated with the socket.

The socket must be in blocking mode; it can have a timeout,
but the file object's internal buffer may cause timeout issues.
"""
for c in mode:
if c not in {'r', 'w', 'b'}:
raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,))
writing = 'w' in mode
reading = 'r' in mode or not writing
assert reading or writing
raw = SocketIO(self, 'wb' if writing else 'rb')
...
return io.BufferedRWPair(reader, writer) if reading and writing else ...

socket.makefile('rb') wraps the socket in a BufferedReader for line-oriented protocols like HTTP/1.1. The socket must be duplicated (socket.dup()) to avoid double-close when both the socket and file are garbage collected.

socket.settimeout

// CPython: Modules/socketmodule.c:2680 sock_settimeout
static PyObject *
sock_settimeout(PySocketSockObject *s, PyObject *arg)
{
double timeout;
if (arg == Py_None) {
/* Blocking mode */
s->sock_timeout = _PyTime_FromSeconds(-1);
internal_setblocking(s, 1);
} else {
timeout = PyFloat_AsDouble(arg);
s->sock_timeout = _PyTime_FromSecondsObject(arg, ...);
/* For non-zero timeout: use select/poll in send/recv */
internal_setblocking(s, 0);
}
Py_RETURN_NONE;
}

socket.settimeout(5.0) sets the socket to non-blocking mode internally but uses select in each send/recv call to implement the timeout. settimeout(0) is equivalent to setblocking(False).

gopy notes

socket.recv_into is module/socket.RecvInto in module/socket/module.go using syscall.Read with a []byte backed by the buffer protocol. socket.sendmsg/recvmsg use syscall.Sendmsg/Recvmsg. socket.makefile returns a module/io.BufferedRWPair. Timeout is implemented with net.Conn.SetDeadline.