Skip to content

한국어 | English

Reference index

03. Sockets

This category covers Socket/ConnectableSocket (the shared base interfaces), CommonSocketOptions and its per-type extensions, the eight concrete socket interfaces, and the shared constants. Every socket's send/publish/request/reply returns the operation-builder family documented in the Messaging category — this category only covers where each builder starts and what each socket type uniquely adds. Sockets are created via the top-level createXxxSocket(ctx) functions (Core category), not a method on Context. The exact signatures are owned by contracts/sockets/.


Socket / ConnectableSocket shared base

The base interfaces every socket type extends: binding, TLS, monitoring, disposal, and (every socket type except StreamSocket) outbound connection.

socket.bind('tcp://*:5555');
socket.setTlsServer(certPath, keyPath, true);
const monitor = socket.monitorOpen([MonitorEventType.Connected]);
socket.close();

Options. Every concrete socket type below extends ConnectableSocket except StreamSocket, which extends Socket directly and adds its own disconnectRid independently (see below). A BaseSocket union type (PairSocket | PubSocket | SubSocket | DealerSocket | RouterSocket | XPubSocket | XSubSocket | StreamSocket) is exported for APIs — such as proxy in the Core category — that accept any concrete socket type.

Member Meaning
bind(endpoint: string) / unbind(endpoint: string) starts/stops listening on an address
close() closes the native socket
monitorOpen(events?: readonly MonitorEventType[], monitorHwmBytes?: bigint) opens a caller-owned pull monitor with an optional event set and byte HWM
setTlsServer(cert, key, requireClientCert?) apply before bind
setTlsClient(ca, hostname, trustSystem?) apply before connect
ConnectableSocket.connect(endpoint: string) / disconnect(endpoint: string) connects/disconnects to a peer address
ConnectableSocket.disconnectRid(routingId: RoutingId) disconnects the peer identified by that routing id

Completion result. All members are synchronous with no return value except monitorOpen, which returns MonitorSocket (Eventing category) synchronously — the caller owns and must close it.

When to use. Call setTlsServer/setTlsClient before bind/connect respectively. Keep the returned monitor and drain it with recv; no callback registration path is installed.


CommonSocketOptions and per-type extensions

The typed options facade shared by every socket type, reached via socket.options. A plain interface of mutable properties (get/set through normal property access) rather than getter/setter method pairs.

socket.options.sendHwm = 100_000n;
socket.options.linger = 1000;
socket.options.submitRetryMode = SubmitRetryMode.LocalFailure;

Options — CommonSocketOptions.

Member Type Meaning
linger number, ms upper bound on how long close() waits for pending sends to flush
sendHwm / recvHwm bigint, accounted-byte HWM outbound/inbound HWM; 0n means unlimited
sendTimeout / recvTimeout / connectTimeout number, ms upper bound on how long a blocking send/receive/connect handshake waits
immediate boolean whether a send requires a live connection now, instead of queueing until one exists
ridDuplicatePolicy RidDuplicatePolicyValue what happens when a peer reuses an existing routing id
ipv6 boolean whether the socket accepts IPv6 connections
tcpNoDelay boolean disables Nagle's algorithm when true
tcpKeepalive number, -1/0/1 OS TCP keepalive mode
maxMsgSize bigint maximum size in bytes of a single accepted message; -1n means no limit
lastEndpoint string, read-only the concrete resolved bind address
backlog number pending-connection queue length for a listening socket
reconnectInterval / reconnectIntervalMax number, ms delay between reconnect attempts / cap on that delay
submitRetryMode typed as plain number, not SubmitRetryModeValue — an inconsistency against ridDuplicatePolicy's typed property whether a failed submit retries automatically on local back-pressure
submitRetryTimeout number, ms retry timeout when submitRetryMode requests it
submitRetryAttempts number retry attempt cap when submitRetryMode requests it

Options — per-type extensions.

Type Member Meaning
DealerSocketOptions probe (boolean) sends an empty probe on connect
requestTimeout (number, ms) request timeout
peerWeight (number, 0-100) load-balancing weight
RouterSocketOptions mandatory (boolean) error instead of silent drop on an unknown route
handover (boolean) convenience wrapper over ridDuplicatePolicy
probe (boolean) sends an empty probe on connect
connectRoutingId (RoutingId \| null, read-only) / setConnectRoutingId(routingId) asymmetric getter/setter naming
requestTimeout / peerWeight same shape as Dealer's, both directions
StreamSocketOptions notify (boolean) delivers peer connect/disconnect as application messages when enabled
PubSocketOptions verbose / verboser (boolean) deliver every (un)subscribe message, including duplicates
noDrop (boolean) error instead of silent drop on back-pressure
manual / manualLastValue (boolean) subscriptions require approveSubscribe/rejectSubscribe; manualLastValue also replays the last cached message per topic to a newly accepted subscriber
topicsCount (number, read-only) active subscription count
welcomeMessage() / setWelcomeMessage(message: MessageLike) sent automatically to each newly connected subscriber; the getter returns a Message the caller owns
approveSubscribe(routingId) / rejectSubscribe(routingId) require manual; set-only, no getters
SubSocketOptions topicsCount (read-only) the only per-type option this socket has

Completion result. Every property read/write is synchronous.

When to use. Set sendHwm/recvHwm and linger before the socket starts exchanging messages when the defaults don't fit the deployment. Read lastEndpoint after binding to a wildcard address.


PairSocket

An exclusive one-to-one peering socket with no routing. Serves as the base shape DealerSocket extends (see below) — unlike dotnet/java/cpp, which give Pair and Dealer a separate shared IMessageSocket-style base, here DealerSocket extends PairSocket directly.

const pair = createPairSocket(ctx);
pair.send().message(Message.from('ping')).submit_sync();
const received = new Received();
if (pair.recv(received)) { /* ... */ }

Options.

Member Meaning
options CommonSocketOptions
send() starts the shared SendOperation builder
recv(result: Received, flags?: RecvFlags) populates result with the next message

Completion result. recv returns booleanfalse only when RecvFlags.DontWait is set and no message is available.

When to use. Use PAIR for an exclusive point-to-point link — it has no peer routing and does not load-balance.


DealerSocket

Load-balances sends across its connected peers and can issue routed requests. Extends PairSocket directly (not a separate shared message-socket interface).

const dealer = createDealerSocket(ctx);
dealer.setRoutingId(RoutingId.from('worker-3'));
const reply = await dealer.request().message(Message.from('payload')).submit();

Options. Everything from PairSocket, plus:

Member Meaning
options overridden to DealerSocketOptions
setRoutingId(routingId) / getRoutingId() assigns/reads this socket's own routing id, observed by peers on connect
request() starts the shared RequestOperation builder; no target parameter — DEALER has no API-level peer routing id

Completion result. recv (inherited) follows the same boolean convention as PairSocket.

When to use. Set setRoutingId before connecting so peers observe it from the first message. DEALER has no protocol envelope helper to reply to an arbitrary token — reply from a received request context (Received.reply()) or an explicit ROUTER reply surface instead.


RouterSocket

Routes messages to peers addressed by routing id, and can reply to a specific peer's request. Extends ConnectableSocket directly (not PairSocket).

const router = createRouterSocket(ctx);
await router.send(peerRid).message(Message.from('hello')).submit();

Options.

Member Meaning
options RouterSocketOptions
send(routingId) starts the shared SendOperation, addressed to that peer
recv(result: Received, flags?: RecvFlags) populates result with the next message
setRoutingId(routingId) / getRoutingId() assigns/reads this socket's own routing id, observed by peers on connect
request(peerRid) Messaging category's RequestOperation, addressed to a specific peer
reply(peerRid, token: ReplyToken) Messaging category's ReplyOperation, consuming the opaque capability received from this ROUTER

Completion result. Managed send and request completion is delivered only by their Promise or blocking terminal. recv follows the boolean convention above.

When to use. Use request(peerRid)/reply(peerRid, token) for ROUTER-initiated or ROUTER-answered request/reply, where DEALER cannot address a specific peer. Keep the ReplyToken opaque, socket-owned, and one-shot.


PubSocket / XPubSocket

PUB publishes topic-filtered messages, dropping ones with no matching subscriber; XPUB additionally surfaces subscriber subscription/unsubscription events. XPubSocket extends PubSocket.

const pub = createPubSocket(ctx);
pub.publish('prices').message(Message.from(tick)).submit();

const xpub = createXPubSocket(ctx);
const evt = new SubscriptionEvent();
if (xpub.receiveSubscriptionEvent(evt)) { /* ... */ }

Options. PubSocket extends ConnectableSocket; XPubSocket extends PubSocket.

Member Meaning
options PubSocketOptions
publish(topic: string) starts the shared SendOperation builder
receiveSubscriptionEvent(result: SubscriptionEvent, flags?: RecvFlags) XPubSocket only; populates result with the next subscribe/unsubscribe

No setRoutingId/getRoutingId on PubSocket (unlike dotnet's IPubSocket, which has both).

Completion result. receiveSubscriptionEvent returns boolean (same convention as recv above).

When to use. Use XPubSocket specifically to observe subscriber churn via receiveSubscriptionEvent, or manual admission via PubSocketOptions.manual/approveSubscribe/ rejectSubscribe; otherwise the two behave the same for publishing.


SubSocket / XSubSocket

SUB subscribes to topics with subscriptions set as socket options; XSUB carries its subscriptions as messages instead. XSubSocket extends SubSocket {} — a completely empty interface body, the plainest possible delta-only declaration among every wrapper binding covered so far.

const sub = createSubSocket(ctx);
sub.setSubscription('prices.');
const msg = new TopicMessage();
if (sub.subscribe(msg)) { /* ... */ }

Options. SubSocket extends ConnectableSocket.

Member Meaning
options SubSocketOptions
setSubscription(filter: string) / unsetSubscription(filter: string) adds/removes a topic filter; subscriptions accumulate
subscriptionAt(index: number) SubscriptionEntry \| null — the filter at that index
subscribe(result: TopicMessage, flags?: RecvFlags) populates result with the next matching publish

XSubSocket adds nothing at all — every member is the inherited SubSocket surface, unchanged.

Completion result. subscribe returns boolean (same convention as recv above).

When to use. Use SubSocket for the common case; use XSubSocket specifically when subscriptions must be carried as ordinary messages instead — the choice is entirely about which concrete type you construct (createSubSocket vs. createXSubSocket), since the interface itself adds nothing to distinguish them.


StreamSocket

Exchanges framed packets directly with raw TCP peers, outside the zlink wire protocol used by every other socket type. Extends Socket (not ConnectableSocket) and declares its own disconnectRid independently.

const stream = createStreamSocket(ctx);
stream.options.recvMode = StreamRecvMode.Packet;
const packet = new StreamPacket();
if (stream.recvPacket(packet)) { /* use packet.routingId/header/body */ }
packet.close();

Options.

Member Meaning
options StreamSocketOptions
send(routingId) starts the shared SendOperation, addressed to that peer
recv(result: Received, flags?: RecvFlags) pulls the next RAW-mode record
recvPacket(result: StreamPacket, flags?: RecvFlags) pulls the next PACKET-mode header/body pair into reusable storage
setRoutingId(routingId) / getRoutingId() assigns/reads this socket's own routing id, observed by peers on connect
disconnectRid(routingId) declared directly on this interface, since StreamSocket does not inherit ConnectableSocket's copy

Completion result. recv and recvPacket follow the boolean convention above. The caller owns the packet's header/body messages and releases them with packet.close().

When to use. Set options.recvMode to StreamRecvMode.Raw or .Packet before the first successful bind/connect; changing it afterward reports invalid state. Drain the selected pull API.


Socket constants

Shared constant objects and their derived types, referenced across every entry above.

Constant Used by Values
SocketType Internal socket-kind identification Dual-cased: both ANY/PAIR/PUB/SUB/DEALER/ROUTER/XPUB/XSUB/STREAM and Any/Pair/Pub/Sub/Dealer/Router/XPub/XSub/Stream are exported as aliases for the identical numeric values
SOCKET_MONITOR_EVENT_ALL compatibility constant 0x7FFFF; current monitorOpen takes a readonly MonitorEventType[] rather than a numeric mask
RidDuplicatePolicy CommonSocketOptions.ridDuplicatePolicy, RouterSocketOptions.handover Reject, Handover
SubmitRetryMode CommonSocketOptions.submitRetryMode (property itself typed as plain number) Off, LocalFailure
SendFlags exported compatibility constants; not accepted by managed send/request/reply terminals None, DontWait
RecvFlags Every recv/subscribe/receiveSubscriptionEvent None, DontWait
PollEventFlag Poller registration/wait (Eventing category) PollIn, PollOut, PollErr, PollPri, PollCompletion

When to use. Use RecvFlags.DontWait for pull APIs that should return false instead of blocking. Managed send/request/reply terminals deliberately do not expose DontWait; pass a list of MonitorEventType values to filter monitorOpen.


See contracts/sockets/ and the Node binding spec for the full rationale.