runtime:net

TCP sockets. connect() follows the WinterTC Sockets API; listen() yields inbound connections. Bytes move over web streams.

Capability: Net (connect) / NetListen (listen)

Exposed as an ES module under the runtime: scheme. Status: Available.

All I/O is async

All I/O is async over web streams — nothing blocks the event loop. Closing a socket's writable half-closes (sends FIN) while reads continue.

Functions

FunctionTypeDescriptionExample
connect(address, options?)(Address, { secureTransport?, sni?, alpn?, allowHalfOpen? }) => SocketOpen an outbound TCP or TLS connection (the WinterTC Sockets API). Returns a Socket synchronously; .opened settles once connected. address is "host:port" or { hostname, port }. secureTransport: "on" negotiates TLS, "starttls" opens plaintext for a later startTls(); sni overrides the server name (default: the host); alpn offers protocols (the negotiated one is SocketInfo.alpn); allowHalfOpen keeps writing after the peer's FIN.const sock = connect({ hostname: "db.internal", port: 5432 })
listen(options)({ hostname?, port, secureTransport?, cert?, key?, alpn? }) => ListenerBind a listening socket. port 0 picks an ephemeral port (read it from listener.addr). Returns an async-iterable Listener of inbound Sockets. secureTransport: "on" terminates TLS on each accept — pass a PEM cert + key (and optional alpn); the cert/key are inline, so server TLS needs no capability beyond NetListen.const server = listen({ hostname: "127.0.0.1", port: 8080 })

Client

JavaScript
import { connect } from "runtime:net";

// WinterTC connect() — returns a Socket immediately; .opened settles on connect.
const sock = connect({ hostname: "example.com", port: 80 });
await sock.opened;

const writer = sock.writable.getWriter();
await writer.write(new TextEncoder().encode("GET / HTTP/1.0\r\n\r\n"));
await writer.close();

// Decode through TextDecoderStream so a multi-byte character split across two
// chunks is still decoded correctly.
let body = "";
for await (const chunk of sock.readable.pipeThrough(new TextDecoderStream())) {
  body += chunk;
}

Socket

MemberTypeDescription
readableReadableStream<Uint8Array>Incoming bytes.
writableWritableStream<Uint8Array>Outgoing bytes; closing the writer half-closes (FIN).
openedPromise<SocketInfo>Resolves once connected: { remoteAddress, remotePort, localAddress, localPort, alpn }. alpn is the negotiated TLS protocol, else null.
closedPromise<void>Resolves when the socket is fully closed.
close(reason?)Promise<void>Fully close the socket. reason is advisory (WinterTC) and ignored.
startTls()SocketUpgrade a secureTransport: "starttls" socket to TLS in place; returns a new encrypted Socket (the original is consumed).
upgradedbooleanTrue only after a startTls() upgrade.

TLS

JavaScript
import { connect } from "runtime:net";

// TLS client — secureTransport "on" (certificate verification on), offering ALPN.
const sock = connect({ hostname: "example.com", port: 443 }, {
  secureTransport: "on",
  alpn: ["h2", "http/1.1"],
});
const { alpn } = await sock.opened; // negotiated protocol, e.g. "h2" (or null)

Server

JavaScript
import { listen } from "runtime:net";

const server = listen({ hostname: "127.0.0.1", port: 8080 });
const { port } = await server.addr;

for await (const conn of server) {
  conn.readable.pipeTo(conn.writable); // echo each connection
}
JavaScript
import { listen } from "runtime:net";

// Terminate TLS on accept — cert/key are inline PEM (no extra capability).
const server = listen({
  hostname: "127.0.0.1", port: 8443,
  secureTransport: "on", cert: certPem, key: keyPem, alpn: ["h2", "http/1.1"],
});
for await (const conn of server) {
  const { alpn } = await conn.opened; // negotiated protocol
}

Listener

MemberTypeDescription
addrPromise<{ hostname, port }>The bound address (resolves after bind).
accept()Promise<Socket | null>The next connection, or null once closed.
close()Promise<void>Stop listening.
[Symbol.asyncIterator]AsyncIterable<Socket>for await (const conn of server) { … }

Errors

ErrorWhen
TypeErrorAny socket failure — invalid options, or a connect / TLS / I/O error (the latter reject .opened or the streams). The message is prefixed "SocketError: " (WinterTC SocketError).
DOMExceptionname "NotAllowedError" — the Net (connect) or NetListen (listen) capability is not granted.
Last updated on
Edit this page