Zum Inhalt springen
Deutsch

Server-WebSocket

ServerWebSocketActor betreibt einen Server. Clients verbinden sich von außen; der Actor nimmt jede Verbindung an, spawnt pro Verbindung einen Child-Handler und routet eingehende Nachrichten dorthin.

import { ActorSystem, Props, ServerWebSocketActor, Actor } from 'actor-ts';
class Connection extends Actor<WsConnInbound> {
constructor(public readonly id: string) { super(); }
override onReceive(msg: WsConnInbound): void {
if (msg.kind === 'opened') this.log.info(`Verbindung offen: ${this.id}`);
if (msg.kind === 'text') this.log.info(`von ${this.id}: ${msg.payload}`);
if (msg.kind === 'closed') this.log.info(`Verbindung geschlossen: ${this.id}`);
}
}
const server = system.spawn(
Props.create(() => new ServerWebSocketActor({
host: '0.0.0.0',
port: 8080,
onConnection: (id) => Props.create(() => new Connection(id)),
})),
'ws-server',
);

Jede eingehende WS-Verbindung spawnt ein Connection-Child. Nachrichten auf dieser Verbindung kommen als WsConnInbound an; das Framework death-watcht den Verbindungs-Actor, sodass dessen Beendigung den darunterliegenden Socket schließt.

interface ServerWebSocketActorSettings extends BrokerCommonSettings {
host: string;
port: number;
onConnection: (id: string) => Props<WsConnInbound>;
backend?: 'bun' | 'ws' | 'fastify'; // Default Auto-Erkennung
path?: string; // auf einen bestimmten Pfad einschränken
tls?: TlsOptions;
}

onConnection wird für jede neue Verbindung aufgerufen. Gib einen Props für den Per-Connection-Actor zurück — meist eine Klasse, die die ID + den State der Verbindung hält.

{ backend: 'bun' } // Buns eingebauter WS-Server
{ backend: 'ws' } // Node-Paket 'ws' (Default für Node)
{ backend: 'fastify' } // an einen bestehenden Fastify-Server gehängt
BackendRuntime-Eignung
'bun'Nur Bun. Nutzt das native WebSocket von Bun.serve.
'ws'Node + Bun. Nutzt das npm-Paket ws.
'fastify'Teilt sich einen Port mit einem HTTP-Server über @fastify/websocket.

Auto-Erkennung wählt 'bun' auf Bun, 'ws' auf Node.

// Der Per-Connection-Actor sendet über seinen Parent zurück:
override onReceive(msg: WsConnInbound) {
if (msg.kind === 'text') {
msg.respond('echo: ' + msg.payload);
// oder: msg.respondBinary(uint8array);
}
}

Das Framework hängt respond(text) / respondBinary(bytes) / close()-Methoden an jede eingehende Nachricht. Einfaches Request/Response innerhalb einer einzelnen Verbindung.

Für Broadcast (an jeden verbundenen Client senden) hält der Parent-Actor das Child-Set:

// Im Server-Actor:
this.broadcastText('event: ' + JSON.stringify({ ... }));

Die broadcast*-Methoden des Frameworks iterieren jede aktive Verbindung.

new ServerWebSocketActor({
host: '0.0.0.0',
port: 8080,
path: '/feed', // nur Verbindungen auf /feed annehmen
onConnection: ...,
});

Für mehrere Endpoints auf demselben Port spawne mehrere ServerWebSocketActors mit unterschiedlichen paths, oder betreibe einen einzelnen und route innerhalb von onConnection basierend auf der Request-URL.

Terminal-Fenster
npm install ws # für backend: 'ws'
# Bun hat WebSocket-Support eingebaut

Drei gute Einsatzfälle:

  1. Echtzeit-UIs — Updates an Browser-Clients pushen.
  2. Eigene Messaging-Protokolle — Game-Server, Chat-Backends.
  3. Webhooks über WS — Polling durch Push ersetzen.

Für einseitige Streams vom Server zum Client ist SSE einfacher. Für Request/Reply-RPC ist HTTP (mit WS für Upgrade) die Norm.