tcp_listen
result =tcp_listen(port),tcp_accept(listener)
Input: port · Output: result
What it is
tcp_listen(port): port (integer 0-65535, 0 asks the OS for a free ephemeral port) binds and returns a TcpListener handle immediately (does not block). tcp_accept(listener): takes that handle and blocks the calling thread until a client connects, then returns a TcpConn handle for the new connection — call it in a loop to accept multiple clients, one call per connection.
Overloads
One call shape — this function is not overloaded.
| Code | Input | Output | Description |
result = tcp_listen(port), tcp_accept(listener) | port TcpListener or TcpConnnot documented yet | result TcpListener or TcpConn | Returns a TcpListener handle from tcp_listen, and a TcpConn handle from tcp_accept. |
Examples
From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.
function echo_once(listener)
conn = tcp_accept(listener) # blocks for the one client
msg = tcp_recv(conn)
tcp_send(conn, msg)
tcp_close(conn)
end function
listener = tcp_listen(0) # 0 -- let the OS pick a free port
port = tcp_port(listener)
w = spawn("echo_once", listener)
client = tcp_connect("127.0.0.1", port)
tcp_send(client, "hello")
print(tcp_recv(client)) # "hello" -- echoed back
tcp_close(client)
join(w)
hello
from concurrency
How it works
Ahmed asked directly for a minimal TCP socket library, following this file's existing live-handle convention (Value::File/Value::Worker/Value::Channel) — grepped first and confirmed no socket support existed at all. Deliberately synchronous/blocking throughout, matching Qu's existing worker model: spawn("serverFn", listener) is how a script runs a server loop without blocking the caller, exactly the way spawn already offloads any other long-running call. UDP and TLS are explicitly out of scope (see BACKLOG.md) — this is a bare, blocking, TCP-only library, the minimal "can two Qu programs actually talk to each other" primitive. tcp_listen(port) binds 0.0.0.0:port (all interfaces) and returns a Value::TcpListener. TcpListener::accept only needs &self (the OS itself serializes concurrent accepts on the same fd), so the handle is a bare Arc, no Mutex — see Value::TcpListener's own doc comment.
From the note above this builtin in the interpreter, where the reasoning was written down as it was built.
See also
tcp_accept — documented in the same entry.