한국어 | English
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 boolean — false 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.