@std/net

Overview

TCP sockets, TLS client sessions, and DNS resolution over a background reactor.

Four types with one job each: Dns turns a name into an address, TcpStream.connect() opens a connection, TcpListener waits for one, and TlsStream upgrades a connected stream to TLS. Importing the module opens nothing and reads nothing.

Bytes are Int values from 0 to 255, one per octet. Nothing here decodes text: encode a request line or a JSON body yourself before write(), and decode after read(). The encoding belongs to the protocol you are speaking, not to the socket.

The sockets are non-blocking, but the calls are not. A call that has to wait parks the calling thread: one reactor thread keeps every socket in the kernel poll set, and the calling thread sleeps on a condition variable until the reactor hands back a result. Nothing spins and other threads keep running, but the thread that called read() executes nothing else until that read finishes.

Two consequences are worth stating plainly. There is no timeout anywhere in this module and no way to cancel a parked call, so a peer that connects and then goes quiet holds the calling thread for as long as it keeps the socket open; close the stream from another thread to unblock it, and the parked call rejects. And the promise a call returns is already settled when the call returns, so await on it returns or throws immediately: the wait happened inside the call.

One reader and one writer per stream, one accepter per listener. The reactor keeps a single read buffer per socket, so two readers race for the same bytes and two writers interleave theirs.

Failures reject with a String message such as connect failed: ... or recv failed: .... The exception is TcpListener.bind, which throws because it never waits. There is no exception type to match on, so code that must tell failures apart has to look at the message.

write() sends one byte per reactor round trip. That keeps the socket code simple and makes backpressure automatic, but it makes bulk payloads slow: 4 KiB costs 4096 reactor wakeups.

None of this exists on WebAssembly. That target has no reactor, so lookups reject with DNS resolution is unsupported in WebAssembly, bind throws Server sockets are unsupported in WebAssembly, and every other call reports that networking is not supported.

.rnx
import { Dns } from "@std/net";

let ip = await Dns.lookup("127.0.0.1");
print(ip);

When to use it

Reach for @std/net when a program touches the network directly: TcpStream.connect for clients, TcpListener.bind plus accept for servers, TlsStream for encrypted sessions, Dns.lookup for resolution. Every operation parks in the kernel until ready; nothing spins.

Capabilities

  • TcpStream connect/read/write
  • TcpListener bind/accept
  • TlsStream sessions
  • Dns.lookup

Symbols

  • class Dns — Name resolution, one address per call. The only item here that works
  • class TcpListener — A bound socket that hands out connected TcpStreams.
  • class TcpStream — A connected TCP socket. Both peers look the same: the client gets one
  • class TlsStream — A TLS client session layered over a connected TcpStream.