Reference

std/network/tcp

std/network/src/tcp.trb

TCP: TcpListener accepts connections, TcpStream is one, and resolve turns a name into addresses. Everything that waits for the network answers a Task, and a connection's two directions are a Source and a Sink of Bytes (docs/design/NETWORK.md sections 2 and 4).

A socket is a handle of the runtime, an Int: the types here are TorbScript over the natives of runtime/io.c, and a handle is closed exactly once, by the close() the release of its owner runs.

fn resolve

fn resolve(host: String): Task<Result<List<IpAddress>, NetworkError>>

The addresses host names: a literal address as it is, localhost as the two loopback addresses, and every other name through the system's resolver, in the order it answered.

const addresses = resolve("localhost").await()?

Errors

  • NetworkError that isHostNotFound() where the name resolves to nothing.

type TcpListener

shared type TcpListener with Close

A socket that listens for connections. It has an identity - the operating system's socket - so it is a shared type, and it closes when the last reference to it goes.

using listener = TcpListener.listen(SocketAddress(IpAddress.loopback, 0))?
var connection = listener.accept().await()?

Related

fn listen

static fn listen(address: SocketAddress, backlog: Int = 128): Result<TcpListener, NetworkError>

Listens on address. Port 0 asks the system for a free port, which TcpListener.localAddress then says. An IPv6 address listens for IPv6 only, on every system.

Errors

  • NetworkError that isAddressInUse() where another socket has the address.

fn localAddress

fn localAddress(): SocketAddress

Where it listens, with the port the system chose where port 0 was asked for.

fn accept

fn accept(): Task<Result<TcpStream, NetworkError>>

The next connection. Waits until one arrives; a cancelled accept leaves the connection to the next one.

fn acceptor

fn acceptor(): TcpAcceptor

A value that accepts connections on this listener from any task, on any worker: several accept loops on one listening socket, which is how a server serves on every core (docs/design/NETWORK.md section 4). It holds the socket's handle and nothing else, so it moves to another worker with the task that holds it; it does not own the socket, which the listener closes - and then every accept of every acceptor fails with a closed socket.

fn stop

fn stop()

Stops listening before the listener is released: an accept that waits fails with a closed socket, and so does every later one. Stopping twice is nothing. A server that shuts down gracefully calls it; the release of the listener does the same by itself.

fn close

var fn close()

Stops listening, as TcpListener.stop does: what the release of the listener runs.

type TcpAcceptor

type TcpAcceptor

What TcpListener.acceptor answers: the right to accept on a listening socket, as a value that moves between workers. Several acceptors of one listener accept at once, each connection going to exactly one of them. It is the handle and nothing else - no address, no text - because a task moves to an idle worker only where its frame holds plain values of at most 32 bytes each (docs/design/CONCURRENCY.md section 16, "What crosses a worker").

fn accept

fn accept(): Task<Result<TcpStream, NetworkError>>

The next connection, on the worker of the task that asked. Waits until one arrives.

Errors

  • NetworkError that isClosed() once the listener stopped listening or was released.

type TcpStream

shared type TcpStream with Close

One TCP connection: bytes in both directions, in order, until either side ends its half. A shared type, because it is the operating system's socket; it closes when the last reference to it - the stream, its source or its sink - goes.

using stream = TcpStream.connectTo("localhost", 8080).await()?
var writing = stream.sink()
writing.addText("ping").await()?

Related

fn of

static fn of(handle: Int): TcpStream

A stream over a handle the runtime answered.

fn connect

static fn connect(address: SocketAddress): Task<Result<TcpStream, NetworkError>>

A connection to address.

Errors

  • NetworkError that isConnectionRefused() where nothing listens there.

fn connectTo

static fn connectTo(host: String, port: Int): Task<Result<TcpStream, NetworkError>>

A connection to port of host: the host is resolved, and each of its addresses is tried in turn until one connects. The failure of the last one is the failure.

fn localAddress

fn localAddress(): Result<SocketAddress, NetworkError>

The address of this end.

fn remoteAddress

fn remoteAddress(): Result<SocketAddress, NetworkError>

The address of the other end.

fn receive

fn receive(maximum: Int = 65536): Task<Result<Bytes?, NetworkError>>

At most maximum bytes, as soon as any arrived: Some(bytes), or None once the peer ended its half. One receive at a time; bytes that arrive while nobody receives wait in the operating system.

fn receiveBuffer

fn receiveBuffer(maximum: Int = 65536): Task<Result<ArrayList<UInt8>?, NetworkError>>

TcpStream.receive as the ArrayList the bytes arrive in, which a reader that buffers appends without a copy.

fn send

fn send(bytes: Bytes): Task<Result<Void, NetworkError>>

Writes all of bytes; finishes once the operating system took them, which is when a full peer has read.

fn sendBuffer

fn sendBuffer(bytes: ArrayList<UInt8>): Task<Result<Void, NetworkError>>

TcpStream.send for bytes that are an ArrayList already, which is copied once instead of twice.

fn shutdown

fn shutdown(): Result<Void, NetworkError>

Ends this half: the peer reads the end of the stream, and may still answer.

fn source

fn source(chunk: Int = 65536): TcpSource

The reading direction as a Source: at most chunk bytes per next(), and None once the peer ended.

fn sink

fn sink(): TcpSink

The writing direction as a Sink: end() ends this half, close() does nothing of its own.

fn close

var fn close()

Closes the socket. What waits on it fails; the peer reads the end of the stream, or a reset.

type TcpSource

shared type TcpSource with Source<Bytes, NetworkError>

The reading direction of a TcpStream: a Source<Bytes, NetworkError>.

fn of

static fn of(stream: TcpStream, chunk: Int): TcpSource

The source of stream: what TcpStream.source answers.

fn next

var fn next(): Task<Result<Bytes?, NetworkError>>

Not documented.

fn close

var fn close()

Nothing of its own: the stream closes once its last holder is gone.

type TcpSink

shared type TcpSink with Sink<Bytes, NetworkError>

The writing direction of a TcpStream: a Sink<Bytes, NetworkError>.

fn of

static fn of(stream: TcpStream): TcpSink

The sink of stream: what TcpStream.sink answers.

fn add

var fn add(item: Bytes): Task<Result<Void, NetworkError>>

Not documented.

fn end

var fn end(): Task<Result<Void, NetworkError>>

Ends this half of the connection: the peer reads the end of the stream.

fn close

var fn close()

Nothing of its own: the stream closes once its last holder is gone.