Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

net.tcp

import net

Everything here is re-exported by net, so import net is enough and the names are called as net.*. Importing net.tcp on its own works too and reaches the same definitions.

This module provides a complete implementation of the Transmission Control Protocol as specified in IETF RFC 793. It provides an interface for working with connected socket and listening socket alike.

It is meant to be used to provide more controlled and specific TCP-based operating system features and for implementing various standard and custom network protocols and specifications.

The example below shows how to use this module to create a basic HTTP client.

import net

var stream = net.TcpStream()
stream.connect('example.com:80')
stream.write_all('GET / HTTP/1.0\r\nHost: example.com\r\n\r\n')

echo stream.read_as_string()
stream.close()

Like earlier said, this module provides functionally for both connected sockets and listening sockets. A simple demonstration of a listening socket is given below which implements a basic and foundational HTTP server that recieves requests on port 8080 and returns a message containig the address of the client to the said client.

import net

var server = net.TcpStream()
server.bind('0.0.0.0:8080')
echo 'listening on ${server.local_address()}'

while true {
  var client = server.accept()
  client.write_all('hello, ${client.peer_address()}\n')
  client.close()
}

Functions

resolve()

net.resolve(address)

Resolves address - a host:port string whose host may be a name or an IP literal - into every socket address it names, in the order the resolver returned them.

A hostname routinely maps to several addresses (an IPv6 and an IPv4 one at the very least), which is why this returns a list rather than a single address. connect() does its own resolution when handed a name, so this is mainly useful when you need the concrete address first: to connect with a timeout (which requires a literal), to prefer one address family, or simply to look up what a name points at.

import net

echo net.resolve('example.com:443')
# [93.184.215.14:443]

Parameters

  • address (string|SocketAddr) — The host:port to resolve

Returns — list: one or more SocketAddr

Raises Error if the name cannot be resolved, or resolves to nothing

Classes

Shutdown

class net.Shutdown

Used with TcpStream.shutdown() to select which half (or both halves) of a full-duplex TCP connection to shut down. Shutting down a stream only affects the local socket as it is a local operation and does not send anything resembling a FIN/EOF marker to the peer beyond what the underlying platform’s shutdown(2) implementation does.

TcpStream

class net.TcpStream

A TCP socket, in either its connected-stream or listening-server role.

  • printable — has a @to_string(), so echo and print() show something useful

Note: On Unix systems, writes to the underlying socket in SOCK_STREAM mode are made with MSG_NOSIGNAL flag. This suppresses the emission of the SIGPIPE signal when writing to disconnected socket.

Note: It’s a good practice to call close() explicitly once you are done with an instance instead of relying on Zuri to release the socket for you.

Constructor

net.TcpStream(_ptr)

Returns a new instance of a TcpStream.

TcpStream.native_ptr()

net.TcpStream.native_ptr() -> Ptr

Hands out this stream’s underlying native socket handle. _ptr is private the way every field prefixed with _ is, so a sibling module like tls - which needs to take an already-connected TcpStream and wrap it, without belonging to this class or inheriting from it - has no other way to reach it.

Returns Ptr

TcpStream.connect()

net.TcpStream.connect(address, timeout)

Opens a TCP connection to a remote host, turning this instance into a connected stream.

address may be a hostname or an IP literal, combined with a port, e.g. 'example.com:80' or '127.0.0.1:8080'. A hostname may resolve to several addresses; they are tried in turn and the first one that succeeds is used, meaning this call can succeed even though some of the resolved addresses were unreachable.

Pass timeout to bound how long the connection attempt may take before giving up. When a timeout is given, address must already be a concrete ip:port literal rather than a hostname, as no DNS resolution would be performed and no multi-address fallback is guaranteed.

Parameters

  • address (string|SocketAddr) — The host:port to connect to
  • timeout (?int) — Optional milliseconds to wait before giving up; omit for an untimed connection attempt

Raises Error if resolution fails, if every resolved address refuses the connection, or (when timeout is given) if address cannot be parsed as an ip:port literal or the timeout elapses first.

Note: a timeout of 0 is the same as specifying no timeout.

TcpStream.bind()

net.TcpStream.bind(address)

Binds this instance to address and starts listening for incoming connections, turning it into a listening server.

address may be a hostname or an IP literal combined with a port, e.g. '0.0.0.0:8080' or '[::]:8080'; port 0 asks the OS to assign an available ephemeral port, which can then be discovered via local_address(). If address resolves to multiple addresses, binding is attempted against each in turn until one succeeds.

Parameters

  • address (string|SocketAddr) — The host:port to bind and listen on

Raises Error if resolution fails or every resolved address fails to bind (e.g. because it is already in use)

TcpStream.accept()

net.TcpStream.accept() -> ?TcpStream

Accepts a new incoming connection. Only valid once this instance has been bind()-ed.

Blocks until a connection arrives, and returns a fully connected TcpStream for the new client. To find out who connected, call peer_address() on it.

In non-blocking mode (see set_non_blocking()) it never blocks: it returns nil when no connection is waiting. That is an answer, not a failure, so nothing is raised for it.

The accepted stream can carry its own blocking mode, which is a platform’s default rather than this listener’s. Set it explicitly with set_non_blocking() on the returned stream if it matters.

Returns ?TcpStream — a stream connected to the newly accepted client, or nil in non-blocking mode with nobody waiting

Raises Error on an underlying I/O error, or if this instance has not been bound

TcpStream.peer_address()

net.TcpStream.peer_address() -> SocketAddr

Returns the socket address of the remote peer this stream is connected to.

Returns SocketAddr — the peer’s address

Raises Error if this instance is not a connected stream

TcpStream.local_address()

net.TcpStream.local_address() -> SocketAddr

Returns the local socket address of this instance, i.e. the address it connected from if it is a stream, or the address it is listening on if it is a listener.

This is particularly useful for discovering the actual port chosen by the OS after binding to port 0.

Returns SocketAddr — the local address

Raises Error if this instance is neither connected nor bound

TcpStream.shutdown()

net.TcpStream.shutdown(how)

Shuts down the read, write, or both halves of this connection. See Shutdown for the meaning of each value; defaults to Shutdown.BOTH when how is omitted. Only valid on a connected stream. Calling this more than once may return an error on some platforms.

Parameters

  • how (?int) — One of the Shutdown constants

Raises Error if the underlying shutdown(2) call fails, or if this instance is not a connected stream

TcpStream.set_read_timeout()

net.TcpStream.set_read_timeout(timeout)

Sets the timeout for future read()/read_exact()/read_all()/ read_as_string() calls.

Pass a number of milliseconds greater than 0 to bound how long a read may block before raising a timeout error, or pass 0 (or any negative number) to remove the timeout entirely and block indefinitely.

Parameters

  • timeout (number) — Milliseconds, or a negative number to disable the timeout

Raises Error if the platform rejects the value

Note: A set timeout is an upper bound: a future read may still return before that bound is reached, and system timers mean the actual time elapsed before a timeout error can be slightly longer than what was requested.

TcpStream.get_read_timeout()

net.TcpStream.get_read_timeout() -> number

Returns the currently configured read timeout in milliseconds, or -1 if no timeout is set (i.e. reads block indefinitely).

Returns number — milliseconds, or -1 if unset

Note: Some platforms do not provide access to the current timeout.

TcpStream.set_write_timeout()

net.TcpStream.set_write_timeout(timeout)

Sets the timeout for future write()/write_all() calls. Same rules as set_read_timeout(): a number of milliseconds greater than 0 bounds how long a write may block, 0 (or any negative number) disables the timeout.

Parameters

  • timeout (number) — Milliseconds, or a negative number to disable the timeout

Raises Error if the platform rejects the value

TcpStream.get_write_timeout()

net.TcpStream.get_write_timeout() -> number

Returns the currently configured write timeout in milliseconds, or -1 if no timeout is set (i.e. writes block indefinitely).

Returns number — milliseconds, or -1 if unset

Note: Some platforms do not provide access to the current timeout.

TcpStream.peek()

net.TcpStream.peek(length) -> bytes

Peeks at up to length bytes of incoming data without consuming it such that a subsequent read()/read_exact() call will still see the peeked bytes. Defaults to peeking a single byte when length is omitted.

Successful peeks can, and often do, return fewer bytes than length.

Parameters

  • length (number) — The maximum number of bytes to peek

Returns bytes — up to length bytes currently in the receive buffer (nil if none are available yet)

Raises Error on an underlying I/O error

TcpStream.set_nodelay()

net.TcpStream.set_nodelay(nodelay)

Enables or disables TCP_NODELAY (i.e. disables or enables Nagle’s algorithm). When nodelay is enabled, small writes are sent immediately instead of being buffered in the hope of coalescing them with subsequent writes, trading throughput for lower latency.

Parameters

  • nodelay (bool) — true to disable Nagle’s algorithm

Raises Error on an underlying I/O error

TcpStream.get_nodelay()

net.TcpStream.get_nodelay() -> bool

Returns whether TCP_NODELAY is currently enabled on this stream.

Returns bool

TcpStream.set_ttl()

net.TcpStream.set_ttl(ttl)

Sets IP_TTL (the IPv4 time-to-live / IPv6 hop limit) for packets sent on this socket. For a listener, this is the TTL that will be used by sockets it accepts.

Parameters

  • ttl (number) — The time-to-live value, 0-255

Raises Error on an underlying I/O error

TcpStream.get_ttl()

net.TcpStream.get_ttl() -> number

Returns the currently configured IP_TTL value for this socket.

Returns number

Raises Error on an underlying I/O error

TcpStream.get_error()

net.TcpStream.get_error() -> ?string

Retrieves and clears the value of the socket’s SO_ERROR option - i.e. any pending error the OS has recorded for this socket without yet surfacing through a failed read, write, or accept().

Returns ?string — a description of the pending error, or nil if there is none

Raises Error on an underlying I/O error while querying the socket

TcpStream.set_non_blocking()

net.TcpStream.set_non_blocking(nonblocking)

Puts the socket into or out of non-blocking mode. In non-blocking mode, read()/write()/accept() and friends return immediately with an error instead of blocking when the operation would otherwise wait on I/O.

Parameters

  • nonblocking (bool) — true to enable non-blocking mode

Raises Error on an underlying I/O error

TcpStream.read()

net.TcpStream.read(length) -> bytes

Reads up to length bytes from the stream into a newly allocated byte buffer, without necessarily filling it and returns the buffer. It is entirely normal for this to return fewer bytes than length; even when more data will eventually be available. So, callers that need an exact amount of data should call this in a loop or use read_exact() instead.

An empty result means the peer has closed its write half (EOF).

Parameters

  • length (number) — The maximum number of bytes to read

Returns bytes — up to length bytes read from the stream (may be empty on EOF)

Raises Error on an underlying I/O error, or if the configured read timeout elapses first

TcpStream.read_exact()

net.TcpStream.read_exact(length) -> bytes

Reads exactly length bytes from the stream, blocking (subject to the read timeout) until that many bytes have arrived.

If the stream reaches EOF before length bytes have been read, this raises an error; the contents of any bytes already read are lost.

Parameters

  • length (number) — The exact number of bytes to read

Returns bytes — exactly length bytes

Raises Error if EOF is reached early, or on any other underlying I/O error

TcpStream.read_all()

net.TcpStream.read_all() -> bytes

Reads from the stream until EOF, returning everything received as a single byte stream. Since a stream is only closed by the peer (or by calling shutdown()/close()), this will block until the connection is closed. Therefore, do not call this on a stream you expect to stay open, or set a read timeout first.

Returns bytes — every byte read up to EOF

Raises Error on an underlying I/O error

TcpStream.read_as_string()

net.TcpStream.read_as_string() -> string

Reads from the stream until EOF, decoding everything received as UTF-8 text. Like read_all(), this blocks until the peer closes the connection. Fails if the received bytes are not valid UTF-8, in which case the data already read is discarded.

Returns string — every byte read up to EOF, decoded as UTF-8

Raises Error on an underlying I/O error, or if the data is not valid UTF-8

TcpStream.write()

net.TcpStream.write(data) -> number

Writes data to the stream, returning the number of bytes actually written. A successful call may write fewer bytes than data contains. Use write_all() if you need every byte written before continuing.

Parameters

  • data (bytes|string) — The bytes (or UTF-8 text) to write

Returns number — the number of bytes actually written

Raises Error on an underlying I/O error, or if the configured write timeout elapses first

TcpStream.write_all()

net.TcpStream.write_all(data)

Writes the entirety of data to the stream, blocking (subject to the write timeout) and retrying internally until every byte has been written.

Parameters

  • data (bytes|string) — The bytes (or UTF-8 text) to write

Raises Error on an underlying I/O error, or if the configured write timeout elapses first

TcpStream.flush()

net.TcpStream.flush()

Flushes any buffered output. TCP streams are unbuffered at this layer, so this is a no-op and doesn’t currently do anything for TcpStream. This is a no-op provided purely so this class satisfies the same interface as other writable streams in the standard library.

Raises Error on an underlying I/O error

TcpStream.is_connected()

net.TcpStream.is_connected() -> bool

Whether this instance currently wraps a connected stream (i.e. connect() has succeeded and close() has not been called since).

Returns bool

TcpStream.is_bound()

net.TcpStream.is_bound() -> bool

Whether this instance currently wraps a bound listener (i.e. bind() has succeeded and close() has not been called since).

Returns bool

TcpStream.close()

net.TcpStream.close()

Flushes, shuts down, and releases the underlying socket, whether it is a connected stream or a bound listener. It is advised to call this explicitly once you are done with the socket rather than relying on the Zuri garbage collector to do it for you eventually. Safe to call more than once, and safe to call on an instance that was never connected or bound.

TcpStream.to_string()

net.TcpStream.to_string() -> string

A human readable representation of this socket, showing whichever of the connected-stream or bound-listener addresses apply.

Returns string


2026, Richard Ore and Zuri contributors