Liburing 2026.10.29
static
YoSTEALTH/Liburing

Prep: sockets

Accept, connect, send, receive, bind, listen and the other socket operations.

io_uring_prep_recvmsg(sqe: SQE, fd: int, msg: Msghdr, flags: int | None = None) -> bool#

Receives a message into msg (recvmsg); cqe.res is the number of bytes received.

Note

  • Linux 5.3+.
  • TypeError if the iov or control of msg is read-only. msg is held until the completion.
  • cqe.flags has IORING_CQE_F_SOCK_NONEMPTY (Linux 5.19+) when the socket still had data after the receive.

io_uring_prep_recvmsg_multishot(sqe: SQE, fd: int, msg: Msghdr, flags: int | None = None) -> bool#

Receives messages into the provided buffer group (IOSQE_BUFFER_SELECT), one completion per message; parse each buffer with io_uring_recvmsg_validate.

Note

  • Linux 6.0+.
  • Needs IOSQE_BUFFER_SELECT and a buffer group (io_uring_sqe_set_buf_group), and no MSG_WAITALL; each completion takes one buffer: IORING_CQE_F_BUFFER in cqe.flags, the id in cqe.flags >> IORING_CQE_BUFFER_SHIFT.
  • Each buffer starts with an io_uring_recvmsg_out header, then the name (namelen bytes), the control data (controllen bytes) and the payload: cqe.res counts all of it.
  • Check cqe.flags of every completion, whatever cqe.res: one without IORING_CQE_F_MORE (an OSError, OSError: ENOBUFS when the group runs out, a cancel) ends the request; submit a new one to keep receiving.
  • msg only gives namelen and controllen (Msghdr(namelen=16, controllen=0)).
  • TypeError if the iov or control of msg is read-only. msg is held until the completion.

io_uring_prep_sendmsg(sqe: SQE, fd: int, msg: Msghdr, flags: int | None = None) -> bool#

Sends the message msg (sendmsg); cqe.res is the number of bytes sent.

Note

  • Linux 5.3+.
  • msg is held until the completion.
  • With IOSQE_IO_LINK set MSG_WAITALL in flags: a short send does not fail the link otherwise.

io_uring_prep_accept(sqe: SQE, fd: int, addr: Sockaddr | None = None, flags: int | None = None) -> bool#

Accepts a connection on the listening socket fd (accept4); cqe.res is the new fd. addr (optional) gets the peer address at the completion and is held until then.

Example

>>> addr = Sockaddr()
>>> io_uring_prep_accept(sqe, fd, addr)
True
Setup used to run this example
def net(ns):
    '''`net_ring`, with an `sqe` of the ring.'''
    net_ring(ns)
    ns['sqe'] = io_uring_get_sqe(ns['ring'])

Note

io_uring_prep_accept_direct(sqe: SQE, fd: int, addr: Sockaddr | None = None, file_index: int | None = None, flags: int | None = None) -> bool#

Like io_uring_prep_accept, but the connection goes into a direct (registered) descriptor.

Note

io_uring_prep_multishot_accept(sqe: SQE, fd: int, addr: Sockaddr | None = None, flags: int | None = None) -> bool#

Accepts connections repeatedly, one completion per connection (cqe.res is the new fd); addr (optional) gets the peer address.

Note

  • Linux 5.19+.
  • Same as io_uring_prep_accept, but keeps going while IORING_CQE_F_MORE is set; a completion without it (an error, a cancel) ends the request, submit a new one to keep accepting.
  • Every connection overwrites addr, possibly before the last one was read: usually leave it None.

io_uring_prep_multishot_accept_direct(sqe: SQE, fd: int, addr: Sockaddr | None = None, flags: int | None = None) -> bool#

Like io_uring_prep_multishot_accept, but each connection goes into a free direct (registered) descriptor, returned in cqe.res.

Note

io_uring_prep_connect(sqe: SQE, fd: int, addr: Sockaddr) -> bool#

Connects fd to the address addr (connect); cqe.res is 0. addr is held until the completion.

Note

  • Linux 5.5+.

io_uring_prep_bind(sqe: SQE, fd: int, addr: Sockaddr) -> bool#

Binds fd to the address addr (bind); cqe.res is 0. addr is held until the completion.

Note

  • Linux 6.11+.

io_uring_prep_listen(sqe: SQE, fd: int, backlog: int) -> bool#

Marks fd as a listening socket with the given backlog (listen); cqe.res is 0.

Note

  • Linux 6.11+.

io_uring_prep_send(sqe: SQE, sockfd: int, buf: Buffer, flags: int | None = None) -> bool#

Sends buf on the socket sockfd (send); cqe.res is the number of bytes sent.

Note

  • Linux 5.6+.
  • buf is held (locked: no resize) until the completion.
  • With IOSQE_IO_LINK set MSG_WAITALL in flags: a short send does not fail the link otherwise.

io_uring_prep_send_bundle(sqe: SQE, sockfd: int, len: int | None = None, flags: int | None = None) -> bool#

Sends a bundle of provided buffers (IOSQE_BUFFER_SELECT) in one request, len at most bytes (None/0: all that fit).

Note

  • Linux 6.10+ (IORING_FEAT_RECVSEND_BUNDLE). The man page says len must be 0, else OSError: EINVAL.
  • Needs IOSQE_BUFFER_SELECT and the group of a buffer ring (io_uring_sqe_set_buf_group): sends from it until it runs out of buffers, which also serializes sends in flight on one socket.
  • One completion: cqe.res is the total number of bytes sent, cqe.flags >> IORING_CQE_BUFFER_SHIFT the first buffer id; the rest follow it in ring order until cqe.res bytes are covered.

io_uring_prep_send_set_addr(sqe: SQE, dest_addr: Sockaddr) -> bool#

Sets the destination address of a send already prepared on this sqe (UDP); dest_addr is held until the completion.

Note

io_uring_prep_sendto(sqe: SQE, sockfd: int, buf: Buffer, addr: Sockaddr, flags: int | None = None) -> bool#

Sends buf to the address addr (sendto, UDP); cqe.res is the number of bytes sent. addr and buf are held until the completion.

Note

  • Function arguments position has changed for C origin for better usability.
  • addr must suit the socket's family.

io_uring_prep_send_zc(sqe: SQE, sockfd: int, buf: Buffer, flags: int | None = None, zc_flags: int | None = None) -> bool#

Zero-copy send of buf; zc_flags are IORING_RECVSEND_* flags. Completes twice: the result, then a notification (IORING_CQE_F_NOTIF) once buf can be reused.

Note

  • Linux 6.0+.
  • The first completion is the usual one: cqe.res is the number of bytes sent (OSError on failure), and IORING_CQE_F_MORE in cqe.flags says the notification follows (also after a failure: check the flag first). The notification has the same user_data, cqe.res 0 and IORING_CQE_F_NOTIF.
  • Do not change buf before the notification; the ring holds it (locked: no resize) until then. A notification says nothing about the data having been sent or received.
  • Zero copy is not guaranteed; OSError: EOPNOTSUPP means the protocol has none, use io_uring_prep_send.
  • IORING_SEND_ZC_REPORT_USAGE in zc_flags: the notification's cqe.res is IORING_NOTIF_USAGE_ZC_COPIED if the data was copied after all, else 0.
  • OSError: ENOMEM can mean a too low locked memory limit (ulimit -l).
  • With IOSQE_IO_LINK set MSG_WAITALL in flags: a short send does not fail the link otherwise.

io_uring_prep_send_zc_fixed(sqe: SQE, sockfd: int, buf: Buffer, buf_index: int | None = None, flags: int | None = None, zc_flags: int | None = None) -> bool#

Zero-copy send of buf, which must lie in the registered buffer buf_index (None: 0).

Note

io_uring_prep_sendmsg_zc(sqe: SQE, fd: int, msg: Msghdr, flags: int | None = None) -> bool#

Zero-copy io_uring_prep_sendmsg: completes twice, the result then a notification (IORING_CQE_F_NOTIF) once the buffers can be reused. msg is held until the completion.

Note

  • Linux 6.1+.
  • The completions are those of io_uring_prep_send_zc: IORING_CQE_F_MORE on the first means the notification follows; do not change the iov buffers of msg before it.
  • OSError: ENOMEM can mean a too low locked memory limit (ulimit -l).

io_uring_prep_sendmsg_zc_fixed(sqe: SQE, fd: int, msg: Msghdr, buf_index: int, flags: int | None = None) -> bool#

Zero-copy io_uring_prep_sendmsg whose iov buffers lie in the registered buffer buf_index.

Note

io_uring_prep_recv(sqe: SQE, sockfd: int, buf: Buffer | None = None, flags: int | None = None) -> bool#

Receives into buf from the socket sockfd (recv); cqe.res is the number of bytes received.

Note

  • Linux 5.6+.
  • buf may be None when the buffer comes from a provided buffer group (IOSQE_BUFFER_SELECT): then cqe.flags has IORING_CQE_F_BUFFER and the buffer id in cqe.flags >> IORING_CQE_BUFFER_SHIFT.
  • buf is held (locked: no resize) until the completion.
  • cqe.flags has IORING_CQE_F_SOCK_NONEMPTY (Linux 5.19+) when the socket still had data after the receive.

io_uring_prep_recv_multishot(sqe: SQE, sockfd: int, buf: Buffer | None = None, flags: int | None = None) -> bool#

Like io_uring_prep_recv, but keeps receiving, one completion per message, while IORING_CQE_F_MORE is set.

Note

  • Linux 6.0+.
  • buf is normally None: the buffers come from a provided buffer group (IOSQE_BUFFER_SELECT and io_uring_sqe_set_buf_group, required), one per completion (IORING_CQE_F_BUFFER, the id in cqe.flags >> IORING_CQE_BUFFER_SHIFT). A buf only caps each receive at len(buf) bytes (fairness between many sockets). MSG_WAITALL is not allowed.
  • Check cqe.flags of every completion, whatever cqe.res: one without IORING_CQE_F_MORE (an OSError, the peer closing, OSError: ENOBUFS when the group runs out, a cancel) ends the request; submit a new one to keep receiving. Return used buffers to the ring promptly.

io_uring_prep_shutdown(sqe: SQE, fd: int, how: int) -> bool#

Shuts down part of a full-duplex connection (shutdown); how is SHUT_RD, SHUT_WR or SHUT_RDWR. cqe.res is 0.

Note

  • Linux 5.11+.

io_uring_prep_socket(sqe: SQE, domain: int, type: int, protocol: int | None = None, flags: int | None = None) -> bool#

Creates a socket (socket); cqe.res is the new fd. protocol and flags default to 0.

Note

  • Linux 5.19+.
  • flags is unused by the kernel so far (the SOCK_* type flags go into type).

io_uring_prep_socket_direct(sqe: SQE, domain: int, type: int, protocol: int | None = None, file_index: int | None = None, flags: int | None = None) -> bool#

Creates a socket into a direct (registered) descriptor. protocol and flags default to 0.

Note

io_uring_prep_cmd_sock(sqe: SQE, cmd_op: int, fd: int, level: int, optname: int, optval: Buffer) -> bool#

Runs a socket command (io_uring_socket_op) on fd; optval is the data going in or out.

Example #1

>>> buf = bytearray((1).to_bytes(4, "little"))
>>> io_uring_prep_cmd_sock(
...     sqe, io_uring_socket_op.SOCKET_URING_OP_SETSOCKOPT, sockfd, SOL_SOCKET, SO_KEEPALIVE, buf,
... )
True
Setup used to run this example
def net(ns):
    '''`net_ring`, with an `sqe` of the ring.'''
    net_ring(ns)
    ns['sqe'] = io_uring_get_sqe(ns['ring'])

Example #2

# or: a bytes option
>>> buf = bytearray(b'eth1')
>>> io_uring_prep_cmd_sock(
...     sqe, io_uring_socket_op.SOCKET_URING_OP_SETSOCKOPT, sockfd, SOL_SOCKET, SO_BINDTODEVICE, buf,
... )
True

Opcode

io_uring_socket_op
    SOCKET_URING_OP_SIOCINQ
    SOCKET_URING_OP_SIOCOUTQ
    SOCKET_URING_OP_GETSOCKOPT
    SOCKET_URING_OP_SETSOCKOPT
    SOCKET_URING_OP_TX_TIMESTAMP
    SOCKET_URING_OP_GETSOCKNAME

Note

  • Linux 6.7+ (SOCKET_URING_OP_SIOCINQ, SOCKET_URING_OP_SIOCOUTQ, SOCKET_URING_OP_GETSOCKOPT, SOCKET_URING_OP_SETSOCKOPT); SOCKET_URING_OP_TX_TIMESTAMP 6.17+; SOCKET_URING_OP_GETSOCKNAME 6.19+.
  • optval is held (locked: no resize) until the completion.
  • SOCKET_URING_OP_SIOCINQ / SOCKET_URING_OP_SIOCOUTQ: cqe.res is the number of unread / unsent bytes queued (OSError: EINVAL on a listening socket); level, optname and optval are ignored.
  • SOCKET_URING_OP_GETSOCKOPT: SOL_SOCKET options only; the option is written into optval and cqe.res is its size. SOCKET_URING_OP_SETSOCKOPT: cqe.res is 0.
  • SOCKET_URING_OP_GETSOCKNAME: the bound address is written into optval (truncated if too short) and cqe.res is its full size; see io_uring_prep_cmd_getsockname.
  • SOCKET_URING_OP_TX_TIMESTAMP: multishot (IORING_CQE_F_MORE), one completion per transmit timestamp of a socket set up with SO_TIMESTAMPING; the ring needs IORING_SETUP_CQE32 or IORING_SETUP_CQE_MIXED (the timestamp is in cqe.big_cqe), cqe.res is the timestamp key (TCP: byte offset, UDP: packet count) and the upper bits of cqe.flags the type; the last completion (no IORING_CQE_F_MORE) has cqe.res 0 or raises the OSError.
  • The kernel checks len(optval) for the option (an int option needs 4 bytes, else OSError: EINVAL).
  • optval is raw bytes in the host's byte order: int.to_bytes(4, sys.byteorder) for an int option.

io_uring_prep_cmd_getsockname(sqe: SQE, fd: int, sockaddr: Sockaddr, peer: int | None = None) -> bool#

Gets the local address of fd (peer=0, the default) or of its peer (peer=1) into sockaddr, written at the completion (getsockname / getpeername); sockaddr is held until then.

Example

>>> sockaddr = Sockaddr()
>>> sqe = io_uring_get_sqe(ring)
>>> io_uring_prep_cmd_getsockname(sqe, sockfd, sockaddr)
True
Setup used to run this example
def net_ring(ns):
    '''A ring, `sockfd` (a TCP socket, `SO_KEEPALIVE` on) and `fd` (a listening one).'''
    make_ring(ns)
    sock = keep(ns, socket.socket())
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    ns['sockfd'] = sock.fileno()
    ns['fd'] = keep(ns, socket.create_server(('127.0.0.1', 0))).fileno()

Note

  • Linux 6.19+.
  • cqe.res is 0; sockaddr gets the address and its length. A non-socket fd gives OSError: ENOTSUP (not ENOTSOCK like the system calls).
Generated by tools/setu_docs.py from the docstrings of Liburing 2026.10.29 (CPython 3.14+).