@eryx/net Module

JSON

High-level TCP and UDP networking helpers built on top of @eryx/_socket.

This module wraps the low-level BSD-style socket API with friendlier client/server classes, socket-option helpers, IPv4/IPv6 family selection, and both signal-driven and manual server accept loops.

Quick start - TCP client

local net = require("@eryx/net")

local client = net.TcpClient.new("127.0.0.1", 8080, {
	nodelay = true,
	timeout = 5,
})

client:write("Hello, server!")
local response = client:read(1024)
print(buffer.tostring(response))
client:close()

Quick start - concurrent TCP server

local net = require("@eryx/net")

local server = net.TcpServer.new("0.0.0.0", 8080, {
	reuseAddress = true,
	handler = function(client)
		client:write("hello\\n")
		client:close()
	end,
})

Quick start - UDP

local net = require("@eryx/net")

local server = net.UdpServer.new("127.0.0.1", 9000)
local client = net.UdpClient.new("127.0.0.1", 9000)

client:write("ping")
local data, host, port = server:receive(1024)
server:writeTo("pong", host, port)

print(buffer.tostring(data))
client:close()
server:close()

Summary

Classes

socket: _socket.Socket
host: string
port: number
family: number
TcpClient.new(host: string, port: number, options: TcpClientOptions?)TcpClient
TcpClient._fromConnectedSocket(socket: _socket.Socket, host: string, port: number, family: number?, options: TcpClientOptions?)TcpClient
TcpClient:write(data: string | buffer)()
TcpClient:read(bytes: number)buffer
TcpClient:setTimeout(seconds: number?)()
TcpClient:setSocketOption(level: number, option: number, value: number | boolean)()
TcpClient:getSocketOption(level: number, option: number)number
TcpClient:getPeerName()(string, number)
TcpClient:getSockName()(string, number)
TcpClient:shutdown(how: number)()
socket: _socket.Socket
host: string
port: number
family: number
TcpClientNonBlocking.new(host: string, port: number, options: TcpClientOptions?)TcpClientNonBlocking
TcpClientNonBlocking._fromConnectedSocket(socket: _socket.Socket, host: string, port: number, family: number?, options: TcpClientOptions?)TcpClientNonBlocking
TcpClientNonBlocking:write(data: string | buffer)boolean
TcpClientNonBlocking:read(bytes: number)buffer?
TcpClientNonBlocking:setSocketOption(level: number, option: number, value: number | boolean)()
TcpClientNonBlocking:getSocketOption(level: number, option: number)number
TcpClientNonBlocking:getPeerName()(string, number)
TcpClientNonBlocking:getSockName()(string, number)
TcpClientNonBlocking:shutdown(how: number)()
socket: _socket.Socket
onClient: Signal.Signal<TcpClient>
onError: Signal.Signal<any>
host: string
port: number
family: number
_listening: boolean
_mode: "signal" | "manual"
_clientOptions: TcpClientOptions?
TcpServer.new(host: string, port: number, options: TcpServerOptions?)TcpServer
TcpServer:handle(handler: ((client: TcpClient) → ()))()
TcpServer:getSockName()(string, number)
socket: _socket.Socket
host: string
port: number
family: number
UdpClient.new(host: string, port: number, options: UdpClientOptions?)UdpClient
UdpClient:write(data: string | buffer)number?
UdpClient:writeTo(data: string | buffer, host: string, port: number)number?
UdpClient:read(bytes: number)buffer?
UdpClient:readFrom(bytes: number)(buffer?, string?, number?)
UdpClient:setTimeout(seconds: number?)()
UdpClient:setSocketOption(level: number, option: number, value: number | boolean)()
UdpClient:getSocketOption(level: number, option: number)number
UdpClient:getPeerName()(string, number)
UdpClient:getSockName()(string, number)
socket: _socket.Socket
onDatagram: Signal.Signal<buffer, string, number>
onError: Signal.Signal<any>
host: string
port: number
family: number
_listening: boolean
_mode: "signal" | "manual"
_packetSize: number
UdpServer.new(host: string, port: number, options: UdpServerOptions?)UdpServer
UdpServer:receive(bytes: number)(buffer?, string?, number?)
UdpServer:writeTo(data: string | buffer, host: string, port: number)number?
UdpServer:setTimeout(seconds: number?)()
UdpServer:setSocketOption(level: number, option: number, value: number | boolean)()
UdpServer:getSocketOption(level: number, option: number)number
UdpServer:getSockName()(string, number)

API Reference

Classes

TcpClient

A blocking TCP client wrapper.

All read and write operations suspend the current coroutine until the operation completes or the configured timeout is hit.

Properties

socket: _socket.Socket

Underlying connected socket.

host: string

Remote host this client is connected to.

port: number

Remote port this client is connected to.

family: number

Address family in use, such as AF_INET or AF_INET6.

TcpClient.new

Creates and connects a blocking TCP client.

TcpClient.new(host: string, port: number, options: TcpClientOptions?)TcpClient

Parameters

host: string

Remote hostname or numeric address.

port: number

Remote TCP port.

Optional socket configuration.

Returns

A connected blocking TCP client.

TcpClient._fromConnectedSocket

Wraps an already-connected socket as a TcpClient.

This is primarily used internally by TcpServer.accept, but can also be useful for advanced code that obtains connected sockets elsewhere.

TcpClient._fromConnectedSocket(socket: _socket.Socket, host: string, port: number, family: number?, options: TcpClientOptions?)TcpClient

Parameters

socket: _socket.Socket

Already-connected TCP socket.

host: string

Remote peer address.

port: number

Remote peer port.

family: number?

Address family override.

Optional wrapper configuration to apply.

Returns

Wrapped blocking TCP client.

TcpClient:write

⚠ Yields

Sends the provided data to the remote peer.

TcpClient:write(data: string | buffer)()

Parameters

data: string | buffer

Payload to send.

TcpClient:read

⚠ Yields

Reads up to bytes bytes from the remote peer.

TcpClient:read(bytes: number)buffer

Parameters

bytes: number

Maximum number of bytes to receive.

Returns

buffer

Received data.

TcpClient:setTimeout

Updates the blocking timeout for future operations on this client.

Passing nil restores blocking mode with no timeout.

TcpClient:setTimeout(seconds: number?)()

Parameters

seconds: number?

Timeout in seconds, or nil for no timeout.

TcpClient:setSocketOption

Sets a socket option on the underlying connection.

TcpClient:setSocketOption(level: number, option: number, value: number | boolean)()

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant such as SO_KEEPALIVE.

value: number | boolean

Value to set.

TcpClient:getSocketOption

Reads a socket option from the underlying connection.

TcpClient:getSocketOption(level: number, option: number)number

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant to query.

Returns

number

Current option value.

TcpClient:getPeerName

Returns the remote address and port of this connection.

TcpClient:getPeerName()(string, number)

Returns

string

Remote host.

number

Remote port.

TcpClient:getSockName

Returns the local address and port used by this connection.

TcpClient:getSockName()(string, number)

Returns

string

Local host.

number

Local port.

TcpClient:shutdown

Shuts down one or both halves of the TCP connection.

TcpClient:shutdown(how: number)()

Parameters

how: number

One of _socket.SHUT_RD, _socket.SHUT_WR, or _socket.SHUT_RDWR.

TcpClient:close

Closes the TCP connection.

TcpClient:close()()

TcpClientNonBlocking

A non-blocking TCP client wrapper.

Read operations return nil when no data is available yet, and write operations return false when the socket would block.

Properties

socket: _socket.Socket

Underlying connected socket.

host: string

Remote host this client is connected to.

port: number

Remote port this client is connected to.

family: number

Address family in use, such as AF_INET or AF_INET6.

TcpClientNonBlocking.new

Creates and connects a non-blocking TCP client.

TcpClientNonBlocking.new(host: string, port: number, options: TcpClientOptions?)TcpClientNonBlocking

Parameters

host: string

Remote hostname or numeric address.

port: number

Remote TCP port.

Optional socket configuration.

Returns

A connected non-blocking TCP client.

TcpClientNonBlocking._fromConnectedSocket

Wraps an already-connected socket as a TcpClientNonBlocking.

TcpClientNonBlocking._fromConnectedSocket(socket: _socket.Socket, host: string, port: number, family: number?, options: TcpClientOptions?)TcpClientNonBlocking

Parameters

socket: _socket.Socket

Already-connected TCP socket.

host: string

Remote peer address.

port: number

Remote peer port.

family: number?

Address family override.

Optional wrapper configuration to apply.

Returns

Wrapped non-blocking TCP client.

TcpClientNonBlocking:write

Attempts to send the full payload without blocking.

TcpClientNonBlocking:write(data: string | buffer)boolean

Parameters

data: string | buffer

Payload to send.

Returns

boolean

true when the payload was fully sent, false when the socket would block.

TcpClientNonBlocking:read

Attempts to read up to bytes bytes without blocking.

TcpClientNonBlocking:read(bytes: number)buffer?

Parameters

bytes: number

Maximum number of bytes to receive.

Returns

buffer?

Received data, or nil if the socket would block.

TcpClientNonBlocking:setSocketOption

Sets a socket option on the underlying connection.

TcpClientNonBlocking:setSocketOption(level: number, option: number, value: number | boolean)()

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant such as SO_KEEPALIVE.

value: number | boolean

Value to set.

TcpClientNonBlocking:getSocketOption

Reads a socket option from the underlying connection.

TcpClientNonBlocking:getSocketOption(level: number, option: number)number

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant to query.

Returns

number

Current option value.

TcpClientNonBlocking:getPeerName

Returns the remote address and port of this connection.

TcpClientNonBlocking:getPeerName()(string, number)

Returns

string

Remote host.

number

Remote port.

TcpClientNonBlocking:getSockName

Returns the local address and port used by this connection.

TcpClientNonBlocking:getSockName()(string, number)

Returns

string

Local host.

number

Local port.

TcpClientNonBlocking:shutdown

Shuts down one or both halves of the TCP connection.

TcpClientNonBlocking:shutdown(how: number)()

Parameters

how: number

One of _socket.SHUT_RD, _socket.SHUT_WR, or _socket.SHUT_RDWR.

TcpClientNonBlocking:close

Closes the TCP connection.

TcpClientNonBlocking:close()()

TcpServer

A TCP server wrapper.

In signal mode, a background accept loop dispatches each connection through TcpServer.onClient. In manual mode, callers explicitly use TcpServer.accept or TcpServer.acceptNonBlocking.

Properties

socket: _socket.Socket

Underlying listening socket.

onClient: Signal.Signal<TcpClient>

Fired for each accepted client in signal mode.

onError: Signal.Signal<any>

Fired when the background accept loop encounters an error.

host: string

Bound local host.

port: number

Bound local port.

family: number

Address family in use, such as AF_INET or AF_INET6.

_listening: boolean
_mode: "signal" | "manual"
_clientOptions: TcpClientOptions?

TcpServer.new

Creates and starts a TCP server.

When options.mode is "signal" or omitted, the server immediately starts a background accept loop. When set to "manual", no background loop is started and callers should use TcpServer.accept themselves.

TcpServer.new(host: string, port: number, options: TcpServerOptions?)TcpServer

Parameters

host: string

Local address to bind to.

port: number

Local port to listen on. Use 0 to let the OS choose.

Optional listener configuration.

Returns

A listening TCP server.

TcpServer:accept

⚠ Yields

Accepts the next incoming connection as a blocking TcpClient.

In manual mode this is typically called by user code. In signal mode it is used internally by the background accept loop.

TcpServer:accept()TcpClient?

Returns

Accepted client, or nil when the listening socket is non-blocking and no client is ready.

TcpServer:acceptNonBlocking

⚠ Yields

Accepts the next incoming connection as a non-blocking TcpClientNonBlocking.

TcpServer:acceptNonBlocking()TcpClientNonBlocking?

Returns

Accepted client, or nil when the listening socket is non-blocking and no client is ready.

TcpServer:handle

Registers a handler on TcpServer.onClient.

TcpServer:handle(handler: ((client: TcpClient) → ()))()

Parameters

handler: ((client: TcpClient) → ())

Callback to run for each accepted client.

TcpServer:getSockName

Returns the bound local address and port of the listening socket.

TcpServer:getSockName()(string, number)

Returns

string

Local host.

number

Local port.

TcpServer:stopListening

Stops accepting new connections and closes the listening socket.

TcpServer:stopListening()()

UdpClient

A UDP client wrapper.

Unlike TCP, UDP is datagram-oriented: each send corresponds to one packet and reads may return complete datagrams from a connected peer.

Properties

socket: _socket.Socket

Underlying UDP socket.

host: string

Default remote host.

port: number

Default remote port.

family: number

Address family in use, such as AF_INET or AF_INET6.

UdpClient.new

Creates a UDP socket and connects it to a default remote peer.

Connected UDP sockets can still use UdpClient.writeTo to override the destination per datagram.

UdpClient.new(host: string, port: number, options: UdpClientOptions?)UdpClient

Parameters

host: string

Default remote hostname or numeric address.

port: number

Default remote UDP port.

Optional socket configuration.

Returns

Connected UDP client wrapper.

UdpClient:write

⚠ Yields

Sends one datagram to the connected peer.

UdpClient:write(data: string | buffer)number?

Parameters

data: string | buffer

Datagram payload.

Returns

number?

Number of bytes written, or nil if the socket would block.

UdpClient:writeTo

⚠ Yields

Sends one datagram to an explicit destination.

UdpClient:writeTo(data: string | buffer, host: string, port: number)number?

Parameters

data: string | buffer

Datagram payload.

host: string

Destination host.

port: number

Destination port.

Returns

number?

Number of bytes written, or nil if the socket would block.

UdpClient:read

⚠ Yields

Receives one datagram payload from the connected peer.

UdpClient:read(bytes: number)buffer?

Parameters

bytes: number

Maximum datagram size to receive.

Returns

buffer?

Datagram payload, or nil if the socket would block.

UdpClient:readFrom

⚠ Yields

Receives one datagram along with its sender address.

UdpClient:readFrom(bytes: number)(buffer?, string?, number?)

Parameters

bytes: number

Maximum datagram size to receive.

Returns

buffer?

Datagram payload.

string?

Sender host.

number?

Sender port.

UdpClient:setTimeout

Updates the blocking timeout for future operations on this client.

Passing nil restores blocking mode with no timeout.

UdpClient:setTimeout(seconds: number?)()

Parameters

seconds: number?

Timeout in seconds, or nil for no timeout.

UdpClient:setSocketOption

Sets a socket option on the underlying UDP socket.

UdpClient:setSocketOption(level: number, option: number, value: number | boolean)()

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant such as SO_BROADCAST.

value: number | boolean

Value to set.

UdpClient:getSocketOption

Reads a socket option from the underlying UDP socket.

UdpClient:getSocketOption(level: number, option: number)number

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant to query.

Returns

number

Current option value.

UdpClient:getPeerName

Returns the default remote peer for this connected UDP socket.

UdpClient:getPeerName()(string, number)

Returns

string

Remote host.

number

Remote port.

UdpClient:getSockName

Returns the local address and port used by this UDP socket.

UdpClient:getSockName()(string, number)

Returns

string

Local host.

number

Local port.

UdpClient:close

Closes the UDP socket.

UdpClient:close()()

UdpServer

A UDP server wrapper.

In signal mode, a background receive loop dispatches datagrams through UdpServer.onDatagram. In manual mode, callers explicitly use UdpServer.receive.

Properties

socket: _socket.Socket

Underlying bound UDP socket.

onDatagram: Signal.Signal<buffer, string, number>

Fired with (data, host, port) for each received datagram in signal mode.

onError: Signal.Signal<any>

Fired when the background receive loop encounters an error.

host: string

Bound local host.

port: number

Bound local port.

family: number

Address family in use, such as AF_INET or AF_INET6.

_listening: boolean
_mode: "signal" | "manual"
_packetSize: number

UdpServer.new

Creates and binds a UDP server socket.

When options.mode is "signal", the server immediately starts a background receive loop that fires UdpServer.onDatagram.

UdpServer.new(host: string, port: number, options: UdpServerOptions?)UdpServer

Parameters

host: string

Local address to bind to.

port: number

Local UDP port. Use 0 to let the OS choose.

Optional socket configuration.

Returns

Bound UDP server wrapper.

UdpServer:receive

⚠ Yields

Receives one datagram and its sender address.

UdpServer:receive(bytes: number)(buffer?, string?, number?)

Parameters

bytes: number

Maximum datagram size to receive.

Returns

buffer?

Datagram payload.

string?

Sender host.

number?

Sender port.

UdpServer:writeTo

⚠ Yields

Sends one datagram to the specified destination.

UdpServer:writeTo(data: string | buffer, host: string, port: number)number?

Parameters

data: string | buffer

Datagram payload.

host: string

Destination host.

port: number

Destination port.

Returns

number?

Number of bytes written, or nil if the socket would block.

UdpServer:setTimeout

Updates the blocking timeout for future operations on this server socket.

Passing nil restores blocking mode with no timeout.

UdpServer:setTimeout(seconds: number?)()

Parameters

seconds: number?

Timeout in seconds, or nil for no timeout.

UdpServer:setSocketOption

Sets a socket option on the underlying UDP socket.

UdpServer:setSocketOption(level: number, option: number, value: number | boolean)()

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant such as SO_BROADCAST.

value: number | boolean

Value to set.

UdpServer:getSocketOption

Reads a socket option from the underlying UDP socket.

UdpServer:getSocketOption(level: number, option: number)number

Parameters

level: number

Protocol level such as SOL_SOCKET.

option: number

Option constant to query.

Returns

number

Current option value.

UdpServer:getSockName

Returns the local address and port of the bound UDP socket.

UdpServer:getSockName()(string, number)

Returns

string

Local host.

number

Local port.

UdpServer:stopListening

Stops the background receive loop, if any, and closes the UDP socket.

UdpServer:stopListening()()

Types

SocketOption

A single socket option assignment used by the higher-level net wrappers.

Each entry maps directly to one setsockopt call on the underlying socket.

level: number

Protocol level such as SOL_SOCKET or IPPROTO_TCP.

name: number

Option constant such as SO_REUSEADDR or TCP_NODELAY.

value: number | boolean

Value to assign to the option.

SocketConfig

Common socket configuration shared by TCP and UDP clients and servers.

All fields are optional. When omitted, the wrapper chooses sensible defaults for the socket kind being created.

family: number?

Address family, typically AF_INET or AF_INET6.

timeout: number?

Blocking timeout in seconds. Ignored in non-blocking mode.

blocking: boolean?

Whether the wrapper should operate in blocking mode. Defaults to true.

socketOptions: { SocketOption }?

Extra raw socket options to apply after the socket is created.

reuseAddress: boolean?

Enables SO_REUSEADDR.

keepAlive: boolean?

Enables SO_KEEPALIVE.

nodelay: boolean?

Enables TCP_NODELAY for TCP sockets.

broadcast: boolean?

Enables SO_BROADCAST for UDP broadcast traffic.

receiveBufferSize: number?

Sets SO_RCVBUF.

sendBufferSize: number?

Sets SO_SNDBUF.

ipv6Only: boolean?

Sets IPV6_V6ONLY on IPv6 sockets.

localHost: string?

Optional local address to bind before connect.

localPort: number?

Optional local port to bind before connect.

TcpClientOptions

Options for TcpClient.new and TcpClientNonBlocking.new.

family: number?

Address family, typically AF_INET or AF_INET6.

timeout: number?

Blocking timeout in seconds. Ignored in non-blocking mode.

blocking: boolean?

Whether the wrapper should operate in blocking mode. Defaults to true.

socketOptions: { SocketOption }?

Extra raw socket options to apply after the socket is created.

reuseAddress: boolean?

Enables SO_REUSEADDR.

keepAlive: boolean?

Enables SO_KEEPALIVE.

nodelay: boolean?

Enables TCP_NODELAY for TCP sockets.

broadcast: boolean?

Enables SO_BROADCAST for UDP broadcast traffic.

receiveBufferSize: number?

Sets SO_RCVBUF.

sendBufferSize: number?

Sets SO_SNDBUF.

ipv6Only: boolean?

Sets IPV6_V6ONLY on IPv6 sockets.

localHost: string?

Optional local address to bind before connect.

localPort: number?

Optional local port to bind before connect.

TcpServerOptions

Options for TcpServer.new.

backlog: number?

Maximum queued connection count passed to listen.

mode: "signal" | "manual"?

signal starts a background accept loop; manual leaves accepting to the caller.

handler: (((client: TcpClient) → ()))?

Optional convenience handler connected to onClient.

family: number?

Address family, typically AF_INET or AF_INET6.

timeout: number?

Blocking timeout in seconds. Ignored in non-blocking mode.

blocking: boolean?

Whether the wrapper should operate in blocking mode. Defaults to true.

socketOptions: { SocketOption }?

Extra raw socket options to apply after the socket is created.

reuseAddress: boolean?

Enables SO_REUSEADDR.

keepAlive: boolean?

Enables SO_KEEPALIVE.

nodelay: boolean?

Enables TCP_NODELAY for TCP sockets.

broadcast: boolean?

Enables SO_BROADCAST for UDP broadcast traffic.

receiveBufferSize: number?

Sets SO_RCVBUF.

sendBufferSize: number?

Sets SO_SNDBUF.

ipv6Only: boolean?

Sets IPV6_V6ONLY on IPv6 sockets.

localHost: string?

Optional local address to bind before connect.

localPort: number?

Optional local port to bind before connect.

UdpClientOptions

Options for UdpClient.new.

family: number?

Address family, typically AF_INET or AF_INET6.

timeout: number?

Blocking timeout in seconds. Ignored in non-blocking mode.

blocking: boolean?

Whether the wrapper should operate in blocking mode. Defaults to true.

socketOptions: { SocketOption }?

Extra raw socket options to apply after the socket is created.

reuseAddress: boolean?

Enables SO_REUSEADDR.

keepAlive: boolean?

Enables SO_KEEPALIVE.

nodelay: boolean?

Enables TCP_NODELAY for TCP sockets.

broadcast: boolean?

Enables SO_BROADCAST for UDP broadcast traffic.

receiveBufferSize: number?

Sets SO_RCVBUF.

sendBufferSize: number?

Sets SO_SNDBUF.

ipv6Only: boolean?

Sets IPV6_V6ONLY on IPv6 sockets.

localHost: string?

Optional local address to bind before connect.

localPort: number?

Optional local port to bind before connect.

UdpServerOptions

Options for UdpServer.new.

mode: "signal" | "manual"?

signal starts a background receive loop; manual leaves receiving to the caller.

handler: (((data: buffer, host: string, port: number) → ()))?

Optional convenience handler connected to onDatagram.

packetSize: number?

Datagram buffer size used by the background receive loop.

family: number?

Address family, typically AF_INET or AF_INET6.

timeout: number?

Blocking timeout in seconds. Ignored in non-blocking mode.

blocking: boolean?

Whether the wrapper should operate in blocking mode. Defaults to true.

socketOptions: { SocketOption }?

Extra raw socket options to apply after the socket is created.

reuseAddress: boolean?

Enables SO_REUSEADDR.

keepAlive: boolean?

Enables SO_KEEPALIVE.

nodelay: boolean?

Enables TCP_NODELAY for TCP sockets.

broadcast: boolean?

Enables SO_BROADCAST for UDP broadcast traffic.

receiveBufferSize: number?

Sets SO_RCVBUF.

sendBufferSize: number?

Sets SO_SNDBUF.

ipv6Only: boolean?

Sets IPV6_V6ONLY on IPv6 sockets.

localHost: string?

Optional local address to bind before connect.

localPort: number?

Optional local port to bind before connect.