Skip to content

Dies ist eine Low-Level-API, die für Bibliotheksautoren und fortgeschrittene Anwendungsfälle gedacht ist.

Starten eines Servers (Bun.listen())

Um einen TCP-Server mit Bun.listen zu starten:

ts
Bun.listen({
  hostname: "localhost",
  port: 8080,
  socket: {
    data(socket, data) {}, // vom Client empfangene Nachricht
    open(socket) {}, // Socket geöffnet
    close(socket, error) {}, // Socket geschlossen
    drain(socket) {}, // Socket bereit für mehr Daten
    error(socket, error) {}, // Fehler-Handler
  },
});

Eine API, die für Geschwindigkeit entwickelt wurde">

In Bun wird ein Satz von Handlern einmal pro Server deklariert, anstatt Callbacks jedem Socket zuzuweisen, wie bei Node.js EventEmitters oder der Web-Standard-WebSocket-API.

ts
Bun.listen({
  hostname: "localhost",
  port: 8080,
  socket: {
    open(socket) {},
    data(socket, data) {},
    drain(socket) {},
    close(socket, error) {},
    error(socket, error) {},
  },
});

Bei leistungsempfindlichen Servern kann das Zuweisen von Listenern zu jedem Socket erheblichen Garbage-Collector-Druck verursachen und die Speichernutzung erhöhen. Im Gegensatz dazu allokiert Bun nur eine Handler-Funktion für jedes Ereignis und teilt sie unter allen Sockets. Dies ist eine kleine Optimierung, aber sie summiert sich.

Kontextuelle Daten können einem Socket im open-Handler angehängt werden.

ts
type SocketData = { sessionId: string };

Bun.listen<SocketData>({
  hostname: "localhost",
  port: 8080,
  socket: {
    data(socket, data) {
      socket.write(`${socket.data.sessionId}: ack`); 
    },
    open(socket) {
      socket.data = { sessionId: "abcd" }; 
    },
  },
});

Um TLS zu aktivieren, übergeben Sie ein tls-Objekt, das key- und cert-Felder enthält.

ts
Bun.listen({
  hostname: "localhost",
  port: 8080,
  socket: {
    data(socket, data) {},
  },
  tls: {
    // kann string, BunFile, TypedArray, Buffer oder Array davon sein
    key: Bun.file("./key.pem"), 
    cert: Bun.file("./cert.pem"), 
  },
});

Die key- und cert-Felder erwarten die Inhalte Ihres TLS-Schlüssels und -Zertifikats. Dies kann ein String, BunFile, TypedArray oder Buffer sein.

ts
Bun.listen({
  // ...
  tls: {
    key: Bun.file("./key.pem"), // BunFile
    key: fs.readFileSync("./key.pem"), // Buffer
    key: fs.readFileSync("./key.pem", "utf8"), // string
    key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")], // Array davon
  },
});

Das Ergebnis von Bun.listen ist ein Server, der der TCPSocket-Schnittstelle entspricht.

ts
const server = Bun.listen({
  /* config*/
});

// Aufhören zu lauschen
// Parameter bestimmt, ob aktive Verbindungen geschlossen werden
server.stop(true);

// Bun-Prozess beenden lassen, auch wenn Server noch lauscht
server.unref();

Eine Verbindung herstellen (Bun.connect())

Verwenden Sie Bun.connect, um eine Verbindung zu einem TCP-Server herzustellen. Geben Sie den Server, mit dem verbunden werden soll, mit hostname und port an. TCP-Clients können denselben Satz von Handlern wie Bun.listen definieren, plus ein paar Client-spezifische Handler.

ts
// Der Client
const socket = await Bun.connect({
  hostname: "localhost",
  port: 8080,

  socket: {
    data(socket, data) {},
    open(socket) {},
    close(socket, error) {},
    drain(socket) {},
    error(socket, error) {},

    // Client-spezifische Handler
    connectError(socket, error) {}, // Verbindung fehlgeschlagen
    end(socket) {}, // Verbindung vom Server geschlossen
    timeout(socket) {}, // Verbindung abgelaufen
  },
});

Um TLS zu erfordern, geben Sie tls: true an.

ts
// Der Client
const socket = await Bun.connect({
  // ... config
  tls: true, 
});

Hot Reloading

Sowohl TCP-Server als auch Sockets können mit neuen Handlern hot-reloaded werden.

ts
const server = Bun.listen({
  /* config */
});

// reloadt Handler für alle aktiven Server-seitigen Sockets
server.reload({
  socket: {
    data() {
      // neuer 'data'-Handler
    },
  },
});
ts
const socket = await Bun.connect({
  /* config */
});

socket.reload({
  data() {
    // neuer 'data'-Handler
  },
});

Pufferung

Derzeit puffern TCP-Sockets in Bun keine Daten. Für leistungsempfindlichen Code ist es wichtig, die Pufferung sorgfältig zu berücksichtigen. Zum Beispiel dies:

ts
socket.write("h");
socket.write("e");
socket.write("l");
socket.write("l");
socket.write("o");

...schneidet erheblich schlechter ab als dies:

ts
socket.write("hello");

Um dies vorerst zu vereinfachen, erwägen Sie die Verwendung von Buns ArrayBufferSink mit der {stream: true}-Option:

ts
import { ArrayBufferSink } from "bun";

const sink = new ArrayBufferSink();
sink.start({
  stream: true, 
  highWaterMark: 1024,
});

sink.write("h");
sink.write("e");
sink.write("l");
sink.write("l");
sink.write("o");

queueMicrotask(() => {
  const data = sink.flush();
  const wrote = socket.write(data);
  if (wrote < data.byteLength) {
    // zurück in den Sink legen, wenn der Socket voll ist
    sink.write(data.subarray(wrote));
  }
});

NOTE

**Corking**

Unterstützung für Corking ist geplant, aber in der Zwischenzeit muss Backpressure manuell mit dem drain-Handler verwaltet werden.

Bun von www.bunjs.com.cn bearbeitet