DEMIENGINEDOCUMENTATION Everything is free
Networking & HTTP · Game systems

Non-blocking connections and binary stream operations.

Asynchronous TCP client

demi.network.tcp connects to raw TCP services without blocking gameplay. A shared libuv event loop handles connection setup, DNS and socket readiness. TCP is an unencrypted byte stream, not a message protocol. Use HTTPS for REST services and do not send credentials over raw TCP on an untrusted network.

local Tcp = require("demi.network.tcp")
local pending, connection, stage

function on_start()
    local err
    pending, err = Tcp.connect("127.0.0.1", 9000, {timeout_ms = 5000})
    assert(pending, err)
    stage = "connect"
end

function on_update(dt)
    if not pending or not pending:done() then return end
    local response = pending:response()
    pending = nil
    if not response.ok then
        if connection then connection:close() end
        error(response.error)
    end
    if stage == "connect" then
        connection = response.connection
        pending = connection:write("hello\n", {timeout_ms = 5000})
        stage = "write"
    elseif stage == "write" then
        pending = connection:read(4096, {timeout_ms = 5000})
        stage = "read"
    else
        print(response.data) -- One available chunk, not necessarily a whole message.
        connection:close()
    end
end

Connect/read/write return operations with done(), response(), wait() and cancel(). Poll them from main-thread callbacks such as on_update. In a Task.fork worker, operation:wait(timeout_ms) waits on a native completion notification and returns the same response fields as response(), followed by a nil error. Omit the timeout to wait indefinitely; zero checks without blocking. Explicit timeouts must be integers from 0 through 2,147,483,647 milliseconds. Main VM waits are rejected, including calls from its coroutines and on completed operations. A wait timeout returns nil, "timeout"; worker cancellation returns nil, "cancelled". Neither cancels the operation. Native failures still return a response table; inspect ok and error. Responses contain ok, binary-safe data, error_code, error, and a connection for a successful connect. Create handles and connections in their owning VM; TCP userdata cannot be transferred between VMs. Closing a connection terminates its pending operations; open() reports its current state.

A read returns the bytes currently available up to the requested count. It does not promise a whole message or exactly that count. Buffer and decode your own framing. Only one read can be pending on a connection. Read cancellation/timeouts preserve unread buffered data. A write timeout closes the connection because some bytes may already have reached the peer.

Timeouts use milliseconds; zero disables the deadline. Native handles may remain readable after the service shuts down. OS DNS cancellation is best-effort, so shutdown can still wait for a system resolver call.

Android builds need the Internet permission for network access. Keep credentials and private data off unencrypted connections.