RawSocket
struct RawSocketA thin, owning wrapper around a POSIX socket file descriptor.
RawSocket is Movable but intentionally not Copyable.
Duplicating a file descriptor without tracking both copies leads to
double-close bugs and hard-to-find resource leaks.
Lifecycle:
__init__: callssocket(2); raises on failure.__deinit__: callsclose(2)whenfd >= 0.__moveinit__: transfers ownership; sourcefdbecomesINVALID_FD.close(): explicit, idempotent close.
Fields:
fd: The OS file descriptor. INVALID_FD means closed/invalid.
family: Address family (AF_INET or AF_INET6).
kind: Socket type (SOCK_STREAM or SOCK_DGRAM).
Example:
var sock = RawSocket(AF_INET, SOCK_STREAM)
sock.set_reuse_addr(True)
# ... use sock.fd ...
sock.close() # or let it fall out of scope
Implements Movable
- Fields
fd: c_intfamily: c_intkind: c_int
__init__
def __init__(out self, family: Int32, kind: Int32) Create a new socket via socket(2).
Example:
var tcp = RawSocket(AF_INET, SOCK_STREAM)
var udp = RawSocket(AF_INET, SOCK_DGRAM)
- Args
family: Address family (AF_INETorAF_INET6).kind: Socket type (SOCK_STREAMfor TCP,SOCK_DGRAMfor UDP).
Raises NetworkError: If socket(2) returns -1, with the OS errno and
strerror message included.
def __init__(out self, fd: Int32, family: Int32, kind: Int32, _wrap: Bool) Wrap an existing file descriptor without calling socket(2).
Safety:
fd must be a valid, open file descriptor. The caller
transfers ownership — RawSocket.__deinit__ will call
close(fd) exactly once.
- Args
fd: An already-open file descriptor (fromaccept(2)etc.).family: Address family (AF_INETorAF_INET6).kind: Socket type (SOCK_STREAMorSOCK_DGRAM)._wrap: Dummy parameter that disambiguates this overload from the public__init__(family, kind)constructor.
__deinit__
def __deinit__(deinit self) Close the file descriptor if it is open.
Safety: safe to call even after a move because fd is set to
INVALID_FD by the move constructor.
close
def close(mut self) Close the socket explicitly. Idempotent.
Sets fd = INVALID_FD so subsequent calls and the destructor
are no-ops.
set_reuse_addr
def set_reuse_addr(self, enabled: Bool) Set SO_REUSEADDR so the port can be reused immediately after the socket is closed.
Should be called before bind(). This is the default for all
TcpListener instances.
Example:
sock.set_reuse_addr(True)
- Args
enabled:Trueto enable address reuse,Falseto disable.
Raises NetworkError: If setsockopt(2) fails.
set_reuse_port
def set_reuse_port(self, enabled: Bool) Set SO_REUSEPORT for multi-process listener load balancing.
Allows multiple processes or threads to bind the same port. Each accept loop gets a fair share of incoming connections from the kernel.
- Args
enabled:Trueto enable port reuse.
Raises NetworkError: If setsockopt(2) fails.
set_keepalive
def set_keepalive(self, enabled: Bool) Enable or disable SO_KEEPALIVE.
When enabled, the kernel sends TCP keepalive probes on idle connections to detect dead peers.
Example:
stream._socket.set_keepalive(True)
- Args
enabled:Trueto send keepalive probes.
Raises NetworkError: If setsockopt(2) fails.
set_tcp_nodelay
def set_tcp_nodelay(self, enabled: Bool) Disable Nagle's algorithm via TCP_NODELAY.
Must be called on all TCP sockets in flare. Nagle coalesces small writes, which introduces latency that surprises virtually every networking caller.
Example:
sock.set_tcp_nodelay(True)
- Args
enabled:Trueto disable Nagle (send immediately).
Raises NetworkError: If setsockopt(2) fails.
set_recv_timeout
def set_recv_timeout(self, ms: Int) Set a receive timeout via SO_RCVTIMEO.
After the timeout expires, recv/recvfrom returns EAGAIN.
Example:
sock.set_recv_timeout(5_000) # 5 seconds
- Args
ms: Timeout in milliseconds.0disables the timeout.
Raises NetworkError: If setsockopt(2) fails.
set_send_timeout
def set_send_timeout(self, ms: Int) Set a send timeout via SO_SNDTIMEO.
- Args
ms: Timeout in milliseconds.0disables the timeout.
Raises NetworkError: If setsockopt(2) fails.
set_recv_buffer
def set_recv_buffer(self, bytes: Int) Request a kernel receive-buffer size via SO_RCVBUF.
The kernel doubles the request for bookkeeping and clamps it to
net.core.rmem_max; the effective size may be smaller than
bytes. Larger buffers absorb datagram bursts so the kernel
does not drop packets between reactor ticks (which would force
the peer into PTO backoff under load).
- Args
bytes: Requested receive-buffer size in bytes.
Raises NetworkError: If setsockopt(2) fails.
set_send_buffer
def set_send_buffer(self, bytes: Int) Request a kernel send-buffer size via SO_SNDBUF.
- Args
bytes: Requested send-buffer size in bytes.
Raises NetworkError: If setsockopt(2) fails.
set_nonblocking
def set_nonblocking(self, enabled: Bool) Toggle non-blocking mode on the socket.
On macOS/arm64 delegates to flare_set_nonblocking in
libflare_tls.so to avoid a Mojo ABI bug where external_call
silently corrupts the third argument of variadic C functions (like
fcntl) on that platform.
On Linux, calls fcntl directly via external_call.
OwnedDLHandle.get_function crashes on Linux when calling into a
freshly-loaded shared library.
- Args
enabled:Trueto enable non-blocking I/O;Falseto restore blocking mode.
Raises NetworkError: If the underlying fcntl(F_SETFL) call fails.
local_addr
def local_addr(self) -> SocketAddr Return the local address assigned by the OS.
Supports both IPv4 and IPv6 sockets (buffer sized for sockaddr_in6).
Raises NetworkError: If getsockname(2) fails.
peer_addr
def peer_addr(self) -> SocketAddr Return the remote address of the connected peer.
Supports both IPv4 and IPv6 sockets.
Raises NetworkError: If getpeername(2) fails (e.g. not connected).