kex docs Standard Library

Net.Socket

module Net.Socket

Process-owned TCP byte streams and listeners. All blocking operations return typed NetError values; close operations are idempotent.

using Net
using Net.Socket

let listener = TCP.listen(TCP.Endpoint.loopback(Port.from(0).try)).try
let address = listener.localAddress.try
let client = TCP.connect(address).try
client.sendAll("ping".to(Binary).try).try
listener.close

module Net.Socket.TCP

connect

connect(endpoint: Endpoint) -> Result<TCPConnection, NetError>
connect(endpoint: Endpoint, options: ConnectOptions) -> Result<TCPConnection, NetError>

Connects to a TCP endpoint with the backend's bounded connect deadline.

Returns a stream or Connect/Timeout

Examples

Connecting to a line-oriented local service

let endpoint = TCP.Endpoint.host("127.0.0.1", Port.from(9000).try)
let connection = TCP.connect(endpoint).try

listen

listen(endpoint: Endpoint) -> Result<TCPListener, NetError>
listen(endpoint: Endpoint, options: ListenOptions) -> Result<TCPListener, NetError>

Binds and starts listening. Port zero selects an ephemeral local port.

Returns a listener or Connect

Examples

Giving each integration test its own free port

let listener = TCP.listen(TCP.Endpoint.loopback(Port.from(0).try)).try
let port = listener.localAddress.try.port

sendAll

sendAll(connection: TCPConnection, data: Binary) -> Result<Integer, NetError>

Sends every byte, retrying partial operating-system writes internally.

On failure, NetError.progress records how many bytes were accepted before the error. Do not blindly retry the whole payload when progress is present.

Examples

Sending one newline-delimited request

connection.sendAll("status\n".to(Binary).try).try

receiveChunk

receiveChunk(connection: TCPConnection, limit: Integer, timeout: Duration) -> Result<Binary, NetError>

Receives up to limit bytes; EOF is reported as Closed.

A successful result is one available chunk, not necessarily a complete application message. Use receiveExactly, receiveUntil, or receiveLine when the protocol supplies a boundary.

Examples

Reading up to 16 KiB from a streaming response

let chunk = connection.receiveChunk(16 * 1024).try

receiveExactly

receiveExactly(connection: TCPConnection, count: Integer, timeout: Duration) -> Result<Binary, NetError>

Receives exactly count bytes or returns a typed EOF/timeout failure.

Useful after a protocol header has declared the payload length.

Examples

Reading a four-byte frame header

let header = connection.receiveExactly(4).try

receiveUntil

receiveUntil(connection: TCPConnection, delimiter: Binary, limit: Integer, timeout: Duration) -> Result<Binary, NetError>

Receives through the first delimiter without exceeding limit bytes.

The delimiter is included in the returned bytes. An empty delimiter is a Parse error; reaching the bound first is a Limit error.

Examples

Read through the end of an HTTP header section

connection.receiveUntil("\r\n\r\n".to(Binary).try, 65536).try

receiveLine

receiveLine(connection: TCPConnection, limit: Integer, timeout: Duration) -> Result<Binary, NetError>

Receives through a newline without exceeding limit bytes.

The newline remains in the returned binary. Decode and trim only after a complete bounded line has been received.

Examples

Reading a response line with a defensive 8 KiB limit

let line = connection.receiveLine(8192).try.to(String).try.trim

shutdownWrite

shutdownWrite(connection: TCPConnection) -> Result<Void, NetError>

Half-closes the write side while leaving reads available.

accept

accept(listener: TCPListener, timeout: Duration) -> Result<TCPConnection, NetError>

Waits for and returns the next connection accepted by the listener.

A timeout applies to this wait only; it does not become a read timeout on the returned connection.

Examples

Accepting one client in a small test server

let client = listener.accept(5.seconds).try

close

close(connection: TCPConnection) -> Void

Idempotently closes a connected stream.

closed?

closed?(connection: TCPConnection) -> Bool

Returns whether the connected stream owner has stopped

localAddress

localAddress(connection: TCPConnection) -> Result<Endpoint, NetError>

Returns the bound local endpoint, including an ephemeral assigned port.

peerAddress

peerAddress(connection: TCPConnection) -> Result<Endpoint, NetError>

Returns the remote endpoint of a connected stream.

Examples

Recording the peer in an access log

let peer = connection.peerAddress.try
IO.printLine("accepted ${peer.host}:${peer.port.string}")

type Plain

Marker for an unencrypted stream.

type TCPConnection

An opaque connected TCP stream.

type TCPListener

An opaque TCP listening socket.

record Endpoint

A host name or numeric address paired with a validated port.

Fields

host
String
port
Net.Port

record ConnectOptions

Connection deadlines and operating-system socket policy.

Buffer values of zero leave sizing to the operating system. noDelay? disables Nagle's algorithm, which is usually right for request/response traffic; bulk-transfer protocols may prefer fewer, larger packets.

Fields

connectTimeout
Duration optional
noDelay?
Bool optional
keepAlive?
Bool optional
sendBuffer
Integer optional
receiveBuffer
Integer optional

record ListenOptions

Listener queue and policy inherited by accepted connections.

backlog bounds connections waiting for accept. Buffer values of zero keep the platform defaults rather than requesting a particular byte size.

Fields

backlog
Integer optional
reuseAddress?
Bool optional
noDelay?
Bool optional
keepAlive?
Bool optional
sendBuffer
Integer optional
receiveBuffer
Integer optional

module Net.Socket.TCP.Endpoint

host

host(name: String, port: Net.Port) -> Endpoint

Pairs a hostname or numeric address with a port.

Resolution happens when connecting, so this preserves name exactly as supplied rather than validating it as an IP.Address.

Returns the remote or listening endpoint

Examples

Connecting by hostname

TCP.Endpoint.host("cache.internal", Port.from(6379).try)

any

any(port: Net.Port) -> Endpoint

Builds an IPv4 wildcard endpoint for listening on every local interface.

Be deliberate with this in development: unlike loopback, it may expose the service to other machines on the network.

Returns an IPv4 wildcard listening endpoint

Examples

Exposing a production service on port 8080

TCP.Endpoint.any(Port.from(8080).try)

loopback

loopback(port: Net.Port) -> Endpoint

Builds an IPv4 loopback endpoint reachable only from this machine.

Port zero lets the operating system choose a free port, which is useful for tests; ask localAddress which port was assigned after listening.

Returns an IPv4 loopback endpoint

Examples

Starting an isolated test listener

TCP.Endpoint.loopback(Port.from(0).try)

module Net.Socket.UDP

bind

bind(endpoint: Endpoint) -> Result<Socket, NetError>
bind(endpoint: Endpoint, options: BindOptions) -> Result<Socket, NetError>

Binds a datagram socket. Port zero selects an ephemeral local port.

Examples

A local UDP echo test

let socket = UDP.bind(UDP.Endpoint.loopback(Port.from(0).try)).try
let endpoint = socket.localAddress.try

sendTo

sendTo(socket: Socket, endpoint: Endpoint, data: Binary) -> Result<Integer, NetError>

Sends one complete datagram and returns its byte count.

Datagram boundaries are preserved: one sendTo corresponds to one receiveFrom, unless the packet is lost by the network.

Examples

Sending a StatsD-style counter

socket.sendTo(collector, "orders:1|c".to(Binary).try).try

receiveFrom

receiveFrom(socket: Socket, limit: Integer) -> Result<Datagram, NetError>

Receives one datagram no larger than limit bytes.

Oversized packets fail with Limit instead of being silently truncated, so a caller never mistakes a prefix for a complete message.

Examples

Receiving and replying to one packet

let packet = socket.receiveFrom(4096).try
socket.sendTo(packet.source, packet.data).try

close

close(socket: Socket) -> Void

Idempotently closes the socket.

closed?

closed?(socket: Socket) -> Bool

Returns whether the socket owner has stopped

localAddress

localAddress(socket: Socket) -> Result<Endpoint, NetError>

Returns the bound endpoint, including an ephemeral assigned port.

joinMulticast

joinMulticast(socket: Socket, group: Net.IP.Address, interface: Net.IP.Address) -> Result<Void, NetError>

Joins an IPv4 multicast group on the selected local interface. The group must be multicast and the interface must be an IPv4 address.

leaveMulticast

leaveMulticast(socket: Socket, group: Net.IP.Address, interface: Net.IP.Address) -> Result<Void, NetError>

Leaves a membership previously joined with the same group and interface.

type Socket

Connectionless datagrams. A receive limit rejects an oversized datagram instead of returning a silently truncated payload.

let socket = UDP.bind(UDP.Endpoint.loopback(Port.from(0).try)).try
let address = socket.localAddress.try
socket.sendTo(address, "hello".to(Binary).try).try
let packet = socket.receiveFrom(1024).try
socket.close

An opaque bound datagram socket.

record Endpoint

A datagram address paired with a validated port.

Fields

host
String
port
Net.Port

record Datagram

A received datagram and its source endpoint.

Reply to source rather than the socket's local address: UDP has no connection that remembers which peer sent the packet.

Fields

source
Endpoint
data
Binary

record BindOptions

Curated socket policy. Broadcast is opt-in. The receive timeout applies to each receiveFrom call; multicast TTL is bounded to the IP hop-limit range.

Fields

broadcast?
Bool optional
multicastTtl
Integer optional
multicastLoopback?
Bool optional
receiveTimeout
Duration optional

module Net.Socket.UDP.Endpoint

host

host(name: String, port: Net.Port) -> Endpoint

Pairs a hostname or numeric address with a UDP port.

Returns an endpoint using name exactly as supplied

Examples

Addressing a local metrics collector

UDP.Endpoint.host("metrics.internal", Port.from(8125).try)

any

any(port: Net.Port) -> Endpoint

Builds an IPv4 wildcard endpoint for receiving on every local interface.

Returns an IPv4 wildcard endpoint

Examples

Receiving discovery packets on port 9999

UDP.Endpoint.any(Port.from(9999).try)

loopback

loopback(port: Net.Port) -> Endpoint

Builds an IPv4 loopback endpoint reachable only from this machine.

Returns an IPv4 loopback endpoint

Examples

Allocating a free UDP port for a test

UDP.Endpoint.loopback(Port.from(0).try)

module Net.Socket.Unix

connect

connect(address: Address) -> Result<UnixConnection, NetError>
connect(address: Address, options: ConnectOptions) -> Result<UnixConnection, NetError>

Connects to a filesystem-domain listener.

Unix sockets avoid opening a network port and are a good fit for two processes on the same machine, such as a CLI and its background daemon.

Examples
let daemon = Unix.connect(Unix.Address.path("/tmp/my-app.sock").try).try

listen

listen(address: Address) -> Result<UnixListener, NetError>
listen(address: Address, options: ListenOptions) -> Result<UnixListener, NetError>

Binds a new path; an existing filesystem entry is never removed implicitly.

This conservative default protects regular files and also avoids taking over a socket that may still belong to a running service.

sendAll

sendAll(connection: UnixConnection, data: Binary) -> Result<Integer, NetError>

Sends every byte and returns the count.

receiveChunk

receiveChunk(connection: UnixConnection, limit: Integer) -> Result<Binary, NetError>

Receives one bounded chunk; EOF is Closed.

receiveExactly

receiveExactly(connection: UnixConnection, count: Integer) -> Result<Binary, NetError>

Receives exactly count bytes or returns a typed EOF/timeout failure.

receiveUntil

receiveUntil(connection: UnixConnection, delimiter: Binary, limit: Integer) -> Result<Binary, NetError>

Receives through delimiter, including it, within an explicit bound.

Examples

Read through the next newline

connection.receiveUntil("\n".to(Binary).try, 4096).try

receiveLine

receiveLine(connection: UnixConnection, limit: Integer) -> Result<Binary, NetError>

Receives through a newline without exceeding limit bytes.

shutdownWrite

shutdownWrite(connection: UnixConnection) -> Result<Void, NetError>

Half-closes the write side while leaving reads available.

accept

accept(listener: UnixListener) -> Result<UnixConnection, NetError>

Waits for and returns the next stream connection.

close

close(connection: UnixConnection) -> Void

Idempotently closes a stream.

closed?

closed?(connection: UnixConnection) -> Bool

Returns whether the stream owner has stopped

type UnixConnection

Filesystem-domain streams for local IPC. The listener owns and removes only the socket path it successfully created.

let address = Unix.Address.path("/tmp/my-service.sock").try
let listener = Unix.listen(address).try
let client = Unix.connect(address).try
listener.close

An opaque connected filesystem-domain byte stream.

type UnixListener

An opaque filesystem-domain stream listener.

record Address

A validated absolute filesystem socket path.

Fields

path
String

Defined in other modules

record ConnectOptions

Connection and read deadlines for a local IPC client.

Fields

connectTimeout
Duration optional
receiveTimeout
Duration optional

record ListenOptions

Listener queue, stale-socket policy, and per-operation deadlines.

removeStale? removes only a filesystem socket, never a regular file or directory that happens to occupy the requested path.

Fields

backlog
Integer optional
removeStale?
Bool optional
acceptTimeout
Duration optional
receiveTimeout
Duration optional

module Net.Socket.Unix.Address

path

path(value: String) -> Result<Address, NetError>

Validates a nonempty absolute Unix-domain socket path.

Relative paths are rejected so ownership and cleanup always refer to one unambiguous filesystem entry.

Returns the address, or Parse

Examples

Addressing a per-user background service

Unix.Address.path("/tmp/my-app.sock").try

module Net.Socket.TLS

connect

connect(endpoint: Net.Socket.TCP.Endpoint, config: ClientConfig) -> Result<TLSConnection, NetError>

Opens a direct TLS connection with a bounded handshake deadline.

serverName drives both certificate hostname verification and SNI. Pass the DNS name from the URL, not an address it happened to resolve to.

Returns a TLS stream or typed failure

Examples

Opening a verified connection to an HTTPS origin

let endpoint = TCP.Endpoint.host("example.com", Port.from(443).try)
let connection = TLS.connect(endpoint, TLS.ClientConfig {
  serverName: "example.com",
  alpn: ["http/1.1"]
}).try

sendAll

sendAll(connection: TLSConnection, data: Binary) -> Result<Integer, NetError>

Sends every plaintext byte through the TLS stream.

receiveChunk

receiveChunk(connection: TLSConnection, limit: Integer) -> Result<Binary, NetError>

Receives one decrypted chunk no larger than limit.

close

close(connection: TLSConnection) -> Void

Idempotently closes the TLS stream.

closed?

closed?(connection: TLSConnection) -> Bool

Returns whether the TLS connection owner has stopped

type TLSConnection

TLS client streams. Certificate and hostname verification are enabled by default; disabling verification must be an explicit configuration choice.

let endpoint = TCP.Endpoint.host("example.test", Port.from(443).try)
let tls = TLS.connect(endpoint, TLS.ClientConfig {
  serverName: "example.test"
}).try
tls.close

An opaque verified or explicitly unverified TLS byte stream.

record ClientConfig

Client handshake policy. TLS 1.2/1.3 are enabled; verification defaults on.

Fields

serverName
String
verify?
Bool optional
alpn
[String] optional