socket
stdlib/core/socket.hk: methods on the TCP and Unix-domain stream/listener resource types.
Sockets are runtime-managed native resources (HANKI.md §4), like File: the per-actor heap closes one when its last handle goes, and a dropped socket is never leaked; close! releases it eagerly. A socket handle is single-owner and moves, never copies, across actors. split! invalidates a full stream and produces independently movable read and write handles.
Open TCP with net.connect! / net.listen!, or a pathname Unix-domain socket with net.connect_unix! / net.listen_unix!; the methods here read, write, split, accept, close, and reset a client's deadline (TCP and Unix-domain alike). The primitive operations are @intrinsic in sys; this face delegates, and the [net] effect bubbles up through the call.
There is no hermetic test block here: every method bottoms out in a real OS socket via an @intrinsic, with no pure result to assert in the stdlib test pack. These paths are covered end-to-end by the CLI integration tests and example programs.
TcpStream
TcpStream, or net.TcpStream, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl TcpStream
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
Read once, returning up to max bytes. An empty bytes is EOF (the peer closed). Err(NetError) on an I/O error or a closed socket. @no-doctest: reads a real socket; needs a peer, cannot assert in a doctest
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
Write once, returning the count written (which may be less than data.length). For the whole buffer, use net.write_all!. @no-doctest: writes a real socket; needs a peer, cannot assert in a doctest
set_deadline!
def set_deadline!(self, timeout_ms: i32) -> () [net]
Replace this connection's absolute wall-clock deadline. The new budget begins now; negative values mean an immediate poll. An operation that is already ready can still complete without waiting. @no-doctest: mutates a live socket resource
close!
def close!(self) -> () [net]
Release the descriptor now. Idempotent: dropping the last handle also closes a stream, and an explicit close! is therefore an eager optimisation. @no-doctest: side-effecting close; no return value to assert
split!
def split!(self) -> Pair<TcpReadHalf, TcpWriteHalf> [net]
Consume this full handle and return independently movable directional resources. The original handle accepts no later operation. @no-doctest: needs a live TCP connection
TcpReadHalf
TcpReadHalf, or net.TcpReadHalf, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl TcpReadHalf
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
Read once, returning up to max bytes. A locally closed half returns EOF. @no-doctest: reads a real socket; needs a peer
close!
def close!(self) -> () [net]
Close the read direction. The sibling write half remains usable. @no-doctest: side-effecting close; no return value to assert
TcpWriteHalf
TcpWriteHalf, or net.TcpWriteHalf, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl TcpWriteHalf
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
Write once, returning the count accepted. @no-doctest: writes a real socket; needs a peer
close!
def close!(self) -> () [net]
Close the write direction. The peer observes EOF, and the sibling read half remains usable. @no-doctest: side-effecting close; no return value to assert
impl ReadStream<TcpStream>
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
See stream.ReadStream.read!. @no-doctest: reads a real socket; needs a peer
impl WriteStream<TcpStream>
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
See stream.WriteStream.write!. @no-doctest: writes a real socket; needs a peer
impl ReadStream<TcpReadHalf>
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
See stream.ReadStream.read!. @no-doctest: reads a real socket; needs a peer
impl WriteStream<TcpWriteHalf>
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
See stream.WriteStream.write!. @no-doctest: writes a real socket; needs a peer
UnixStream
UnixStream, or net.UnixStream, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl UnixStream
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
Read once, returning up to max bytes. An empty bytes is EOF. @no-doctest: reads a real local socket; needs a peer
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
Write once, returning the count accepted. Use net.write_all! for the whole buffer. @no-doctest: writes a real local socket; needs a peer
set_deadline!
def set_deadline!(self, timeout_ms: i32) -> () [net]
Replace this connection's absolute wall-clock deadline. The new budget begins now; negative values mean an immediate poll. An operation that is already ready can still complete without waiting. @no-doctest: mutates a live socket resource
close!
def close!(self) -> () [net]
Release the descriptor now. Idempotent. @no-doctest: side-effecting close; no return value to assert
split!
def split!(self) -> Pair<UnixReadHalf, UnixWriteHalf> [net]
Consume this full handle and return independently movable directional resources. The original handle accepts no later operation. @no-doctest: needs a live Unix-domain connection
UnixReadHalf
UnixReadHalf, or net.UnixReadHalf, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl UnixReadHalf
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
Read once, returning up to max bytes. A locally closed half returns EOF. @no-doctest: reads a real local socket; needs a peer
close!
def close!(self) -> () [net]
Close the read direction. The sibling write half remains usable. @no-doctest: side-effecting close; no return value to assert
UnixWriteHalf
UnixWriteHalf, or net.UnixWriteHalf, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl UnixWriteHalf
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
Write once, returning the count accepted. @no-doctest: writes a real local socket; needs a peer
close!
def close!(self) -> () [net]
Close the write direction. The peer observes EOF, and the sibling read half remains usable. @no-doctest: side-effecting close; no return value to assert
impl ReadStream<UnixStream>
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
See stream.ReadStream.read!. @no-doctest: reads a real local socket; needs a peer
impl WriteStream<UnixStream>
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
See stream.WriteStream.write!. @no-doctest: writes a real local socket; needs a peer
impl ReadStream<UnixReadHalf>
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
See stream.ReadStream.read!. @no-doctest: reads a real local socket; needs a peer
impl WriteStream<UnixWriteHalf>
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
See stream.WriteStream.write!. @no-doctest: writes a real local socket; needs a peer
impl Stream<UnixStream>
Error
type Error = sys.NetError
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
See stream.Stream.read!. @no-doctest: reads a real local socket; needs a peer
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
See stream.Stream.write!. @no-doctest: writes a real local socket; needs a peer
close!
def close!(self) -> () [net]
See stream.Stream.close!. @no-doctest: side-effecting close; no return value to assert
UnixListener
UnixListener, or net.UnixListener, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl UnixListener
accept!
def accept!(self) -> Result<UnixStream, sys.NetError> [net]
Block for the next local connection. Peer addresses are not exposed. @no-doctest: blocks on a real local accept; needs a peer
close!
def close!(self) -> () [net]
Release the descriptor, leaving the pathname for explicit cleanup with fs.delete!. Idempotent. Unix listeners intentionally have no local_address! method. @no-doctest: side-effecting close; no return value to assert
impl Stream<TcpStream>
The Stream face: framing code written against S: Stream works over a socket unchanged.
Each body forwards to the inherent method of the same name above, which is not the self-call it looks like: inherent-wins coherence (HANKI.md §10) resolves self.read! to the inherent impl, never back into this one. Forwarding in place of repeating the sys calls is what binds the two faces together: a guard added to the inherent method is then also in force for every caller that arrives through the trait.
Error
type Error = sys.NetError
read!
def read!(self, max: u32) -> Result<bytes, sys.NetError> [net]
See stream.Stream.read!. @no-doctest: reads a real socket; needs a peer, cannot assert in a doctest
write!
def write!(self, data: bytes) -> Result<i64, sys.NetError> [net]
See stream.Stream.write!. @no-doctest: writes a real socket; needs a peer, cannot assert in a doctest
close!
def close!(self) -> () [net]
See stream.Stream.close!. @no-doctest: side-effecting close; no return value to assert
impl DeadlineStream<TcpStream>
set_deadline!
def set_deadline!(self, timeout_ms: i32) -> () [net]
See stream.DeadlineStream.set_deadline!. @no-doctest: mutates a live socket resource
impl DeadlineStream<UnixStream>
set_deadline!
def set_deadline!(self, timeout_ms: i32) -> () [net]
See stream.DeadlineStream.set_deadline!. @no-doctest: mutates a live socket resource
TcpListener
TcpListener, or net.TcpListener, is a runtime-managed native resource handle (HANKI.md §4): live native state the per-actor memory manager owns, released when the last handle drops. It is single-owner - never copied, moved across a send - and has no fields of its own, so its methods are its whole surface. A handle is minted by an API that opens one; it is never constructed.
impl TcpListener
accept!
def accept!(self) -> Result<TcpStream, sys.NetError> [net]
Block until the next inbound connection arrives and return its TcpStream. Err(NetError) on an I/O error. @no-doctest: blocks on a real accept; needs a peer, cannot assert in a doctest
local_address!
def local_address!(self) -> Result<sys.LocalAddress, sys.NetError> [net]
The address this listener is bound to. An ephemeral bind (net.listen!(host, 0)) reports the port the OS chose, which nothing else recovers. @no-doctest: needs a bound port; environment-dependent, cannot assert in a doctest
close!
def close!(self) -> () [net]
Release the bound port now. Idempotent, like TcpStream.close!. @no-doctest: side-effecting close; no return value to assert