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.unix

import net

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

Unix domain sockets: the same stream interface as tcp, over a path on the filesystem rather than an address on the network.

A unix socket is how two programs on one machine usually talk when one of them is a server. It skips the network stack, so there is no port to collide with and nothing to reach it from another host. And because the socket is a file, the filesystem decides who may connect: a socket in a directory only one user can enter is reachable by only that user, which is a stronger answer than binding to loopback and trusting everyone on the machine.

import net

var client = net.UnixStream()
client.connect('/var/run/mysqld/mysqld.sock')
client.write_all('hello')

echo client.read(5)
client.close()

A server binds a path and accepts on it:

import net
import os

var server = net.UnixStream()
server.bind('/run/app.sock')

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

Binding leaves a file behind

bind() creates the path and refuses if something is already there, including a socket left by a process that has since died. Closing the socket frees the descriptor but does not remove the file, because by then another process may have bound the same path and removing it would break them. A server that expects to be restarted deletes a stale path itself before binding.

Windows

Windows has unix sockets, but they are not reachable from Zuri. Every call here raises there rather than the module being absent, so a program fails where it tries to connect, saying why, instead of failing at import. is_supported() answers the question in advance.

Functions

is_supported()

net.is_supported() -> bool

Whether unix domain sockets work on this machine.

False on Windows and true everywhere else. A program that can fall back to TCP tests this rather than catching the error.

Returns bool

pair()

net.pair() -> list[UnixStream]

Two sockets already connected to each other, with no path and nothing on the filesystem.

This is the way to hand one end to a child process, or to talk between threads over a real socket without choosing a name that something else might collide with.

Returns list[UnixStream] — The two ends, which are interchangeable.

Raises Error if the pair cannot be created.

Classes

UnixStream

class net.UnixStream

A unix domain socket, connected or listening.

One class covers both, as TcpStream does: connect() makes it a stream and bind() makes it a listener, and the methods that do not apply raise rather than doing something surprising.

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

Constructor

net.UnixStream(_ptr)

Parameters

  • _ptr (Ptr|nil) — An existing native handle, as accept() and pair() produce. A new socket when nil.

UnixStream.native_ptr()

net.UnixStream.native_ptr() -> Ptr

Hands out the underlying native handle, the same way TcpStream does, so a sibling module can wrap an already-connected socket without belonging to this class.

Returns Ptr

UnixStream.connect()

net.UnixStream.connect(path: string)

Connects to the socket at path.

There is no timeout: a unix socket connect either succeeds at once or fails at once, since there is no network in between. Use set_read_timeout() and set_write_timeout() to bound the conversation that follows.

Parameters

  • path (string)

Raises Error if nothing is listening there, if the path does not exist, or if this process may not open it.

UnixStream.bind()

net.UnixStream.bind(path: string)

Creates the socket at path and starts listening on it.

Parameters

  • path (string)

Raises Error if something already exists at that path, including a socket a dead process left behind, or if the directory is not writable.

UnixStream.accept()

net.UnixStream.accept() -> ?UnixStream

Waits for a connection and returns it.

Blocks until someone connects. In non-blocking mode (see set_non_blocking()) it never blocks: it returns nil when nobody is waiting, which is an answer rather than a failure.

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 ?UnixStream — The connected end of the new conversation, or nil in non-blocking mode with nobody waiting.

Raises Error if this socket is not listening.

UnixStream.peer_address()

net.UnixStream.peer_address() -> string|nil

The path the other end is bound to.

nil for a socket that has no path, which is what both ends of a pair() are and what a client that never bound one is.

Returns string|nil

UnixStream.local_address()

net.UnixStream.local_address() -> string|nil

The path this socket is bound to, or nil where it has none.

Returns string|nil

UnixStream.shutdown()

net.UnixStream.shutdown()

Closes both directions without releasing the handle, so a read at the other end returns nothing rather than blocking.

Raises Error if this socket is not connected.

UnixStream.set_read_timeout()

net.UnixStream.set_read_timeout(timeout: number)

Gives up on a read that takes longer than timeout.

Parameters

  • timeout (number) — Milliseconds. Zero means wait forever.

UnixStream.get_read_timeout()

net.UnixStream.get_read_timeout() -> number

The read timeout in milliseconds, zero for none.

Returns number

UnixStream.set_write_timeout()

net.UnixStream.set_write_timeout(timeout: number)

Gives up on a write that takes longer than timeout.

Parameters

  • timeout (number) — Milliseconds. Zero means wait forever.

UnixStream.get_write_timeout()

net.UnixStream.get_write_timeout() -> number

The write timeout in milliseconds, zero for none.

Returns number

UnixStream.set_non_blocking()

net.UnixStream.set_non_blocking(nonblocking: bool)

Whether reads and writes return at once rather than waiting.

A non-blocking socket raises where it would have blocked, which is what net.poll is for: wait there, then read here.

Parameters

  • nonblocking (bool)

UnixStream.read()

net.UnixStream.read(length: number) -> bytes

Reads up to length bytes, returning what arrived.

A shorter result than asked for is normal and does not mean the conversation is over; an empty one does.

Parameters

  • length (number)

Returns bytes

UnixStream.read_exact()

net.UnixStream.read_exact(length: number) -> bytes

Reads exactly length bytes, waiting for as many as it takes.

Parameters

  • length (number)

Returns bytes

Raises Error if the other end closes before that many arrive.

UnixStream.read_all()

net.UnixStream.read_all() -> bytes

Reads until the other end closes.

Returns bytes

UnixStream.read_as_string()

net.UnixStream.read_as_string() -> string

Reads until the other end closes and decodes the result as text.

Returns string

Raises Error if what arrived is not valid UTF-8.

UnixStream.write()

net.UnixStream.write(data) -> number

Writes what it can and reports how much that was.

Parameters

  • data (bytes|string)

Returns number — Bytes written, which may be fewer than given.

UnixStream.write_all()

net.UnixStream.write_all(data)

Writes everything, however many attempts that takes.

Parameters

  • data (bytes|string)

UnixStream.flush()

net.UnixStream.flush()

Pushes out anything held back.

UnixStream.is_connected()

net.UnixStream.is_connected() -> bool

Whether this socket is connected to another.

Returns bool

UnixStream.is_bound()

net.UnixStream.is_bound() -> bool

Whether this socket is listening on a path.

Returns bool

UnixStream.close()

net.UnixStream.close()

Closes the socket. The handle cannot be used afterwards.

A path this socket was bound to stays on the filesystem, since by now another process may have bound it.

UnixStream.to_string()

net.UnixStream.to_string()

2026, Richard Ore and Zuri contributors