Skip to content

Il s'agit d'une API de bas niveau destinée aux auteurs de bibliothèques et aux cas d'utilisation avancés.

Démarrer un serveur (Bun.listen())

Pour démarrer un serveur TCP avec Bun.listen :

ts
Bun.listen({
  hostname: "localhost",
  port: 8080,
  socket: {
    data(socket, data) {}, // message reçu du client
    open(socket) {}, // socket ouvert
    close(socket, error) {}, // socket fermé
    drain(socket) {}, // socket prêt pour plus de données
    error(socket, error) {}, // gestionnaire d'erreur
  },
});

Une API conçue pour la vitesse">

Dans Bun, un ensemble de gestionnaires est déclaré une fois par serveur au lieu d'assigner des callbacks à chaque socket, comme avec les EventEmitters de Node.js ou l'API standard WebSocket.

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

Pour les serveurs sensibles aux performances, l'assignation de listeners à chaque socket peut provoquer une pression significative sur le garbage collector et augmenter l'utilisation de la mémoire. En revanche, Bun n'alloue qu'une seule fonction de gestionnaire pour chaque événement et la partage entre tous les sockets. C'est une petite optimisation, mais elle s'additionne.

Des données contextuelles peuvent être attachées à un socket dans le gestionnaire open.

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" }; 
    },
  },
});

Pour activer TLS, passez un objet tls contenant les champs key et cert.

ts
Bun.listen({
  hostname: "localhost",
  port: 8080,
  socket: {
    data(socket, data) {},
  },
  tls: {
    // peut être une chaîne, BunFile, TypedArray, Buffer, ou un tableau de ceux-ci
    key: Bun.file("./key.pem"), 
    cert: Bun.file("./cert.pem"), 
  },
});

Les champs key et cert attendent le contenu de votre clé TLS et de votre certificat. Cela peut être une chaîne, BunFile, TypedArray, ou Buffer.

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")], // tableau de ce qui précède
  },
});

Le résultat de Bun.listen est un serveur qui se conforme à l'interface TCPSocket.

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

// arrêter l'écoute
// le paramètre détermine si les connexions actives sont fermées
server.stop(true);

// permettre au processus Bun de se terminer même si le serveur écoute toujours
server.unref();

Créer une connexion (Bun.connect())

Utilisez Bun.connect pour vous connecter à un serveur TCP. Spécifiez le serveur auquel vous vous connectez avec hostname et port. Les clients TCP peuvent définir le même ensemble de gestionnaires que Bun.listen, plus quelques gestionnaires spécifiques au client.

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

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

    // gestionnaires spécifiques au client
    connectError(socket, error) {}, // échec de la connexion
    end(socket) {}, // connexion fermée par le serveur
    timeout(socket) {}, // délai d'attente de la connexion dépassé
  },
});

Pour exiger TLS, spécifiez tls: true.

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

Rechargement à chaud

Les serveurs TCP et les sockets peuvent être rechargés à chaud avec de nouveaux gestionnaires.

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

// recharge les gestionnaires pour tous les sockets serveur actifs
server.reload({
  socket: {
    data() {
      // nouveau gestionnaire 'data'
    },
  },
});
ts
const socket = await Bun.connect({
  /* config */
});

socket.reload({
  data() {
    // nouveau gestionnaire 'data'
  },
});

Mise en tampon

Actuellement, les sockets TCP dans Bun ne mettent pas les données en tampon. Pour le code sensible aux performances, il est important de considérer attentivement la mise en tampon. Par exemple, ceci :

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

...performe considérablement moins bien que ceci :

ts
socket.write("hello");

Pour simplifier cela pour l'instant, envisagez d'utiliser ArrayBufferSink de Bun avec l'option {stream: true} :

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) {
    // remettre dans le sink si le socket est plein
    sink.write(data.subarray(wrote));
  }
});

NOTE

**Corking**

La prise en charge du corking est prévue, mais en attendant, la contre-pression doit être gérée manuellement avec le gestionnaire drain.

Bun édité par www.bunjs.com.cn