Sockets
Also known as: socket tcp udp tls ssl quic connection listen accept datagram certificate mtls timeout port
● Intermediate5 minBefore this: HTTPSpec 14.10
std.net speaks the protocols under HTTP: TCP connections, UDP datagrams, TLS encryption and QUIC.
use std.net
fn echo_once(listener: Listener) ! NetError uses Net {
const conn = try listener.accept()
while true {
const data = (try conn.read()) ?? break
try conn.write(data)
}
}
fn main() ! Error {
const listener = try net.listen("127.0.0.1:0")
const _server = spawn echo_once(listener)
const conn = try net.connect(listener.address())
try conn.write("namaste".bytes())
const back = (try conn.read()) ?? Bytes([])
print(back.text() ?? "?")
conn.close()
}The program ran and printed:
kavach run echo.kav
namasteconn.read()gives the bytes that came, ornoneonce the other side has closed:?? breakends the loop then.- While a task waits for the network, the program's other tasks run.
- Addresses are text,
"host:port"; port0asks the system for a free one.
Every function
| Function or method | Gives |
|---|---|
net.listen(address) -> Listener ! NetError | Listens for connections at address |
listener.address() -> String | The address it listens at, with the port the system picked |
listener.accept() -> Connection ! NetError | Waits for the next connection |
net.connect(address) -> Connection ! NetError | A connection to address |
net.connect_tls(address, protocols: [String] = [], roots: String = "", cert: String = "", key: String = "") -> Connection ! NetError | A connection encrypted with TLS (1.3, or 1.2 for servers without 1.3). The server's certificate must be valid for the host name in address, checked against root certificates built into Kavach (decision 0021) and the PEM certificates in roots, if any (a company's own certificate authority); there is no way to skip the check. protocols are offered to the server (ALPN), such as ["h2", "http/1.1"]. With cert and key (PEM), the client proves who it is to a server that asks (mutual TLS) |
net.listen_tls(address, cert, key, protocols: [String] = [], clients: String = "") -> Listener ! NetError | Listens for TLS connections, proving the server's identity with the certificate chain cert and private key key (PEM text, read with fs.read_text where they are files). key takes a secret (8.7), here and in connect_tls, so a key read with env or kept in a secret field needs no reveal. It chooses the first of protocols a client offers. With clients (PEM certificates), every client must present a certificate signed by one of them (mutual TLS); a client without one is refused while connecting |
conn.read() -> Bytes? ! NetError | Waits for data: the bytes that came (at most 64 KB at a time), or none once the other side has closed |
conn.write(data) ! NetError | Sends all of data (Bytes) |
conn.protocol() -> String? | The protocol the two sides agreed on, from those connect_tls offered and listen_tls takes, or none |
conn.peer() -> String | The other side's address: for a connection a listener accepted, whoever opened it (203.0.113.7:51234) |
conn.start_tls(host, protocols: [String] = [], roots: String = "", cert: String = "", key: String = "") -> Connection ! NetError | TLS begun as a client on a connection that has spoken plain TCP so far, the way PostgreSQL's SSLRequest and SMTP's STARTTLS do it. The server's certificate is checked against host, and the other settings are those of connect_tls. It gives the encrypted connection; conn itself is closed from then on, so nothing is sent in the clear by mistake. key takes a secret, as in connect_tls |
conn.accept_tls(cert, key, protocols: [String] = [], clients: String = "") -> Connection ! NetError | The server's side of the same: TLS begun on a connection the server accepted, with the settings of listen_tls; key takes a secret |
conn.peer_certificate() -> Bytes? | The other side's TLS certificate as DER: the server's on a client connection, a client's (mutual TLS) on a server one; none without TLS. For channel binding, such as SCRAM's tls-server-end-point, which hashes it |
conn.client_cert() -> ClientCert? | With mutual TLS (clients: on listen_tls), the names on the certificate the client showed: ClientCert(common_name:, dns:, uris:), from its subject and its subject-alternative names (a SPIFFE id such as spiffe://shop/orders is a URI); none otherwise (decision 0099) |
conn.close() | Closes the connection (or stops listening). A connection or listener is also closed when its last holder lets it go (6.1), so one a function opens and doesn't return is closed when the function ends |
net.bind(address) -> UdpSocket ! NetError | A UDP socket at address |
sock.send(data, to) ! NetError | Sends data (Bytes) as one datagram to the address to |
sock.receive() -> Datagram ! NetError | Waits for the next datagram: Datagram(data: Bytes, from: String), with the sender's address |
sock.address(), sock.close() | As for a listener |
A failed operation gives a NetError: Refused(address), TimedOut(address) or Failed(address, reason).
Limits and sizes
| What | Limit or size | Source |
|---|---|---|
Any network wait (not accept or receive) | gives up after 30 seconds, with TimedOut; .timeout(d) changes it | 10-net.md |
conn.read() | at most 64 KB at a time | 10-net.md |
A UDP datagram | at most 64 KB is read | 10-net.md |
An HTTP server's idle connection | closed after 5 seconds without a request | 11-http.md |
Every limit in Kavach, on one page: Limits and Sizes.
One page for each form
What Kavach does for you
A waiting task costs nothing
A task waiting for the network sleeps on the operating system's event queue, and only the thread that has work wakes up.