Aller au contenu
Français

UDP

Ce contenu n’est pas encore disponible dans votre langue.

UdpSocketActor wraps a UDP socket — connectionless, no acks, no retries, packet-oriented. Use when best-effort delivery is fine and latency matters more than reliability.

Inbound datagrams are pushed to a target actor you wire in through the builder — there is no subscribe command. Sending is a { kind: 'send', datagram } message with an explicit destination (UDP is connectionless, so every packet carries its own address).

import { ActorSystem, UdpSocketActor, UdpSocketOptions } from 'actor-ts';
import type { UdpDatagram } from 'actor-ts';
const system = ActorSystem.create('udp-demo');
// Inbound datagrams land here, one message per packet:
class PacketHandler extends Actor<UdpDatagram> {
override onReceive(d: UdpDatagram): void {
// d.payload — Uint8Array
// d.remoteHost — sender's address
// d.remotePort — sender's port
console.log(new TextDecoder().decode(d.payload), 'from', d.remoteHost);
}
}
const target = system.spawnAnonymous(PacketHandler);
const udpSocketOptions = UdpSocketOptions.create()
.withBindPort(41234) // bind for receiving; 0 lets the OS pick
.withTarget(target);
const udp = system.spawnAnonymous(
() => new UdpSocketActor(
udpSocketOptions, // required: where inbound packets go
),
);
// Send to a remote endpoint:
udp.tell({
kind: 'send',
datagram: { payload: 'ping', host: '127.0.0.1', port: 41234 },
});

UdpSocketOptionsType extends BrokerCommonOptionsType (which carries the shared reconnect / circuit-breaker / outbound-buffer fields) and adds:

interface UdpSocketOptionsType extends BrokerCommonOptionsType {
bindHost?: string; // default '0.0.0.0'
bindPort?: number; // default 0 = OS-assigned
type?: 'udp4' | 'udp6'; // default 'udp4'
target?: ActorRef<UdpDatagram>; // required: inbound subscriber
}

target is the only required field — inbound datagrams have nowhere to go without it. All four are set through the builder:

UdpSocketOptions.create()
.withBindHost('0.0.0.0')
.withBindPort(41234)
.withType('udp4')
.withTarget(target);

Inbound packets are delivered straight to the target actor — one UdpDatagram message per packet. There is no subscribe handshake; wiring the target through .withTarget(..) is the whole subscription:

class PacketHandler extends Actor<UdpDatagram> {
override onReceive(d: UdpDatagram): void {
// d.payload — Uint8Array (packet bytes)
// d.remoteHost — sender's IP address
// d.remotePort — sender's port
this.handleDatagram(d.payload, d.remoteHost, d.remotePort);
}
}
const target = system.spawnAnonymous(PacketHandler);
const udpSocketOptions = UdpSocketOptions.create()
.withBindPort(41234)
.withTarget(target);
const udp = system.spawnAnonymous(
() => new UdpSocketActor(
udpSocketOptions,
),
);

Each packet is one logical message — UDP preserves packet boundaries (unlike TCP’s byte stream), so one datagram in maps to exactly one UdpDatagram out.

Send with a { kind: 'send', datagram } message. The datagram carries its own destination — host and port — plus the payload, which may be a string (UTF-8 encoded for you) or a raw Uint8Array (sent verbatim):

udp.tell({
kind: 'send',
datagram: { payload: 'ping', host: '127.0.0.1', port: 41234 },
});
udp.tell({
kind: 'send',
datagram: { payload: new Uint8Array([0xde, 0xad]), host: '10.0.0.5', port: 8125 },
});

A target is required, but if the actor only ever sends you can still leave binding to the OS. Omit withBindPort (or pass 0) and the socket binds to an ephemeral port — a pure sender for one-way telemetry (statsd, syslog):

const udpSocketOptions = UdpSocketOptions.create().withTarget(target);
new UdpSocketActor(
udpSocketOptions, // OS-assigned port, send-only in practice
);

Three good fits:

  1. Telemetry — sending metrics to a collector (statsd, DogStatsD). Loss of one packet is acceptable; latency matters.
  2. Service discovery on a LAN — mDNS / SSDP / proprietary broadcast schemes.
  3. High-frequency low-stakes data — game positions, sensor streams where the next packet supersedes the previous.

Not the right shape for:

  • Anything that needs delivery guarantee — use TCP, or a higher-level reliable protocol.
  • Anything requiring ordering — UDP packets arrive in any order.
  • Anything larger than MTU — packets >1500 bytes fragment + can drop more easily.

Settings resolve with the usual precedence — explicit builder options override HOCON, which overrides the built-in defaults. The config namespace is actor-ts.io.broker.udp:

actor-ts.io.broker.udp {
bindHost = "0.0.0.0"
bindPort = 41234
type = "udp4"
}