Xterm.js: Flusskontrolle mit XON / XOFF

Erstellt am 10. Nov. 2020  ·  3Kommentare  ·  Quelle: xtermjs/xterm.js

Hallo Mitwirkende,

Ich verwende xtermjs, um eine Terminalanwendung zu erstellen, die im Webbrowser ausgeführt wird, und der Zielserver verwendet Linux. Ich habe festgestellt, dass xtermjs v4.9.0 nicht auf ^ C reagiert, wenn der Befehl yes ausgeführt wird.
Dann habe ich auf v4.0.2 zurückgesetzt und die Option useFlowControl aktiviert, es hat funktioniert.

Das useFlowControl mit XON / XOFF wurde aus Version 2.3.0 (PR # 447) hinzugefügt, aber aus Version 4.1.0 (PR # 2422) entfernt.
Ich kann keine Diskussion über den Grund finden, es zu entfernen. Hat die XON / XOFF-Lösung eine Gefahr?

Wenn nicht, können wir einen Plan haben, um diese Funktion wieder in die Bibliothek zu bringen, oder sollte ich sie in meiner eigenen Anwendung implementieren?

Die im Dokument beschriebene Flusskontrolle (https://xtermjs.org/docs/guides/flowcontrol/) hilft nicht viel, da ich Websocket verwende, um eine Verbindung zum Backend herzustellen.

typquestion

Hilfreichster Kommentar

Wir haben XON / XOFF entfernt, da es in einigen Szenarien nicht zuverlässig funktionierte. Aus dem Hinterkopf erinnere ich mich, dass wir Probleme mit der ZSH-Shell hatten, die die XON / XOFF-Sequenzen für etwas anderes verwendete. Ich glaube, das Windows-Terminal hatte auch Probleme mit diesen Sequenzen.

Wie auch immer - die Art und Weise, wie ich dies gelöst habe (auch mit WebSockets - in meinem Fall socket.io, aber es spielt keine Rolle), besteht darin, manuell einen Flusskontrollmechanismus über den Socket selbst einzurichten.

Wenn also Daten auf dem Socket eintreffen, die in xterm.js geschrieben werden sollen, erhöhen wir einen Zähler. Sobald die Daten erfolgreich in xterm.js geschrieben wurden (was bedeutet, dass sie von xterm.js gerendert wurden), verringern wir diesen Zähler .

Wenn der Zähler einen bestimmten Schwellenwert überschreitet, senden wir eine pause -Nachricht über das Websocket, die auf der Serverseite den Pty-Stream pausiert ( terminalStream.pause() ). Sobald wir diesen Schwellenwert unterschreiten, senden wir eine resume -Nachricht über das Websocket, die auf der Serverseite den Pty-Stream wieder aufnimmt ( terminalStream.resume() ).

Beachten Sie, dass die Methoden terminalStream.pause() und terminalStream.resume() die integrierten Node.js-Stream-Methoden zur Behandlung des Gegendrucks sind. node-pty sowie ssh2 unterstützen die Behandlung des Gegendrucks über diese Methoden.

// client
const MAX_PENDING_WRITES = 5;
let pendingWrites = 0;
let paused = false;
socket.on('data', (data) => {
  pendingWrites++;
  xterm.write(data, () => {
    pendingWrites--;
    if (pendingWrites > MAX_PENDING_WRITES && !paused) {
      paused = true;
      socket.emit('pause');
      return;
    }
    if (pendingWrites <= MAX_PENDING_WRITES && paused) {
      paused = false;
      socket.emit('resume');
      return;
    }
  });
});

// server
terminalStream.on('data', (data) => socket.emit('data', data);
socket.on('data', (data) => terminalStream.write(data));
socket.on('pause', () => terminalStream.pause();
socket.on('resume', () => terminalStream.resume();

Dieser Mechanismus funktioniert bisher ziemlich zuverlässig. Der Befehl yes überflutet die Verbindung nicht mehr. Es gibt immer noch eine Verzögerung von ungefähr 0,5 Sekunden zwischen CTRL+C und der tatsächlichen Beendigung des Befehls in Szenarien mit hohem Durchsatz, aber IMO ist das in Ordnung.

Ich hoffe, es hilft.

Alle 3 Kommentare

Wir haben XON / XOFF entfernt, da es in einigen Szenarien nicht zuverlässig funktionierte. Aus dem Hinterkopf erinnere ich mich, dass wir Probleme mit der ZSH-Shell hatten, die die XON / XOFF-Sequenzen für etwas anderes verwendete. Ich glaube, das Windows-Terminal hatte auch Probleme mit diesen Sequenzen.

Wie auch immer - die Art und Weise, wie ich dies gelöst habe (auch mit WebSockets - in meinem Fall socket.io, aber es spielt keine Rolle), besteht darin, manuell einen Flusskontrollmechanismus über den Socket selbst einzurichten.

Wenn also Daten auf dem Socket eintreffen, die in xterm.js geschrieben werden sollen, erhöhen wir einen Zähler. Sobald die Daten erfolgreich in xterm.js geschrieben wurden (was bedeutet, dass sie von xterm.js gerendert wurden), verringern wir diesen Zähler .

Wenn der Zähler einen bestimmten Schwellenwert überschreitet, senden wir eine pause -Nachricht über das Websocket, die auf der Serverseite den Pty-Stream pausiert ( terminalStream.pause() ). Sobald wir diesen Schwellenwert unterschreiten, senden wir eine resume -Nachricht über das Websocket, die auf der Serverseite den Pty-Stream wieder aufnimmt ( terminalStream.resume() ).

Beachten Sie, dass die Methoden terminalStream.pause() und terminalStream.resume() die integrierten Node.js-Stream-Methoden zur Behandlung des Gegendrucks sind. node-pty sowie ssh2 unterstützen die Behandlung des Gegendrucks über diese Methoden.

// client
const MAX_PENDING_WRITES = 5;
let pendingWrites = 0;
let paused = false;
socket.on('data', (data) => {
  pendingWrites++;
  xterm.write(data, () => {
    pendingWrites--;
    if (pendingWrites > MAX_PENDING_WRITES && !paused) {
      paused = true;
      socket.emit('pause');
      return;
    }
    if (pendingWrites <= MAX_PENDING_WRITES && paused) {
      paused = false;
      socket.emit('resume');
      return;
    }
  });
});

// server
terminalStream.on('data', (data) => socket.emit('data', data);
socket.on('data', (data) => terminalStream.write(data));
socket.on('pause', () => terminalStream.pause();
socket.on('resume', () => terminalStream.resume();

Dieser Mechanismus funktioniert bisher ziemlich zuverlässig. Der Befehl yes überflutet die Verbindung nicht mehr. Es gibt immer noch eine Verzögerung von ungefähr 0,5 Sekunden zwischen CTRL+C und der tatsächlichen Beendigung des Befehls in Szenarien mit hohem Durchsatz, aber IMO ist das in Ordnung.

Ich hoffe, es hilft.

@tandatle Siehe auch die Dokumente zur Flusskontrolle .

Bearbeiten: Entschuldigung, übersehen Sie Ihre Docs Bemerkung. Möchtest du erklären, was dort unklar ist? Ja, der Websocket-Bereich ist nur ein Stub (kein sofort einsatzbereites Snippet), da ich nicht getan habe, um Tonnen von Snippets für verschiedene Socket-Bibliotheken und benutzerdefinierte Anforderungen zu erstellen (dies ist allein aus Sicherheitsgründen mit Websockets nur schwer richtig zu machen). . Sie können immer noch einen konkreten Ausschnitt hinzufügen, der diese Aspekte abdeckt.

@mofux @jerch Danke für deine Hilfe.
Ich verwende nicht node.js im Backend, sondern einen in C ++ geschriebenen Prozess. Daher muss ich möglicherweise weitere Untersuchungen durchführen, um zwischen der Verwendung von XON / XOFF und der Implementierung der Backpresure-Behandlung in meinem Backend-Prozess zu wählen.
Ich danke dir sehr.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

albinekb picture albinekb  ·  4Kommentare

LB-J picture LB-J  ·  3Kommentare

kolbe picture kolbe  ·  3Kommentare

pfitzseb picture pfitzseb  ·  3Kommentare

ghost picture ghost  ·  4Kommentare