Xterm.js: التحكم في التدفق باستخدام XON / XOFF

تم إنشاؤها على ١٠ نوفمبر ٢٠٢٠  ·  3تعليقات  ·  مصدر: xtermjs/xterm.js

مرحبًا أيها المساهمون ،

أنا أستخدم xtermjs لإنشاء تطبيق طرفي يعمل على متصفح الويب ، ويستخدم الخادم الهدف نظام Linux. لقد لاحظت أن xtermjs v4.9.0 لا يستجيب لـ ^ C عند تشغيل الأمر yes .
ثم قمت بنسخ الإصدار 4.0.2 وقمت بتمكين الخيار useFlowControl ، لقد نجحت.

تمت إضافة useFlowControl باستخدام XON / XOFF من الإصدار 2.3.0 (PR # 447) ولكن تمت إزالته من الإصدار 4.1.0 (PR # 2422).
لا أجد أي مناقشة حول سبب إزالته. هل يحتوي حل XON / XOFF على أي مأزق؟

إذا لم يكن الأمر كذلك ، فهل لدينا خطة لإعادة هذه الميزة إلى lib أم ينبغي عليّ تنفيذها على تطبيقي الخاص؟

لا يساعد التحكم في التدفق الموضح في المستند (https://xtermjs.org/docs/guides/flowcontrol/) كثيرًا منذ أن أستخدم مقبس الويب للاتصال بالخلفية.

typquestion

التعليق الأكثر فائدة

أزلنا XON / XOFF لأنه لم يعمل بشكل موثوق في بعض السيناريوهات. أتذكر من الجزء الخلفي من رأسي أننا واجهنا مشاكل مع غلاف ZSH ، الذي استخدم تسلسلات XON / XOFF لشيء مختلف. أعتقد أن Windows Terminal واجهت أيضًا مشاكل مع هذه التسلسلات.

على أي حال - الطريقة التي قمت بحلها (باستخدام WebSockets أيضًا - في حالتي socket.io ولكن لا يهم) هي إنشاء آلية للتحكم في التدفق يدويًا على المقبس نفسه.

لذلك - عندما تصل البيانات إلى المقبس الذي يجب كتابته إلى xterm.js ، نقوم بزيادة العداد ، وبمجرد أن تتم كتابة البيانات بنجاح إلى xterm.js (مما يعني أنه تم تقديمها بواسطة xterm.js) ، نقوم بتقليل هذا العداد .

إذا تجاوز العداد حدًا معينًا ، فإننا نرسل رسالة pause عبر Websocket ، والتي من جانب الخادم ستوقف تدفق pty ( terminalStream.pause() ). بمجرد أن نذهب إلى ما دون هذا الحد ، نرسل رسالة resume عبر Websocket ، والتي على جانب الخادم ستستأنف تدفق pty ( terminalStream.resume() ).

لاحظ أن طريقتين terminalStream.pause() و terminalStream.resume() هما طريقتا node.js Stream المدمجتان للتعامل مع الضغط المرتد. يدعم node-pty بالإضافة إلى ssh2 معالجة الضغط المرتد عبر هذه الطرق.

// 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();

هذه الآلية تعمل بشكل موثوق حتى الآن. لن يؤدي الأمر yes إلى إغراق الاتصال بعد الآن. لا يزال هناك تأخير بنحو 0.5 ثانية بين CTRL+C والإنهاء الفعلي للأمر في سيناريوهات الإنتاجية العالية ، لكن IMO لا بأس به.

اتمني ان يكون مفيدا.

ال 3 كومينتر

أزلنا XON / XOFF لأنه لم يعمل بشكل موثوق في بعض السيناريوهات. أتذكر من الجزء الخلفي من رأسي أننا واجهنا مشاكل مع غلاف ZSH ، الذي استخدم تسلسلات XON / XOFF لشيء مختلف. أعتقد أن Windows Terminal واجهت أيضًا مشاكل مع هذه التسلسلات.

على أي حال - الطريقة التي قمت بحلها (باستخدام WebSockets أيضًا - في حالتي socket.io ولكن لا يهم) هي إنشاء آلية للتحكم في التدفق يدويًا على المقبس نفسه.

لذلك - عندما تصل البيانات إلى المقبس الذي يجب كتابته إلى xterm.js ، نقوم بزيادة العداد ، وبمجرد أن تتم كتابة البيانات بنجاح إلى xterm.js (مما يعني أنه تم تقديمها بواسطة xterm.js) ، نقوم بتقليل هذا العداد .

إذا تجاوز العداد حدًا معينًا ، فإننا نرسل رسالة pause عبر Websocket ، والتي من جانب الخادم ستوقف تدفق pty ( terminalStream.pause() ). بمجرد أن نذهب إلى ما دون هذا الحد ، نرسل رسالة resume عبر Websocket ، والتي على جانب الخادم ستستأنف تدفق pty ( terminalStream.resume() ).

لاحظ أن طريقتين terminalStream.pause() و terminalStream.resume() هما طريقتا node.js Stream المدمجتان للتعامل مع الضغط المرتد. يدعم node-pty بالإضافة إلى ssh2 معالجة الضغط المرتد عبر هذه الطرق.

// 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();

هذه الآلية تعمل بشكل موثوق حتى الآن. لن يؤدي الأمر yes إلى إغراق الاتصال بعد الآن. لا يزال هناك تأخير بنحو 0.5 ثانية بين CTRL+C والإنهاء الفعلي للأمر في سيناريوهات الإنتاجية العالية ، لكن IMO لا بأس به.

اتمني ان يكون مفيدا.

tandatle انظر أيضا مستندات حول flowcontrol .

تحرير: معذرة ، تجاهلت ملاحظة المستندات الخاصة بك. الحرص على شرح ما هو غير واضح هناك؟ نعم ، يعد قسم websocket مجرد كعب (لا يوجد مقتطف جاهز للعمل) ، حيث لم أقم بإنشاء الكثير من المقتطفات لمختلف مقابس المقبس والاحتياجات المخصصة (من الصعب القيام بذلك بشكل صحيح باستخدام مآخذ الويب لأسباب أمنية فقط) . ما زلت لا تتردد في إضافة مقتطف ملموس يغطي تلك الجوانب.

mofuxjerch شكرا لمساعدتكم .
أنا لا أستخدم node.js في الخلفية ، ولكن عملية مكتوبة بلغة C ++ ، لذلك قد أضطر إلى إجراء المزيد من التحقيقات للاختيار بين استخدام XON / XOFF وتنفيذ المعالجة الخلفية في عملية الواجهة الخلفية.
شكرا جزيلا لك.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

fabiospampinato picture fabiospampinato  ·  4تعليقات

ghost picture ghost  ·  4تعليقات

pfitzseb picture pfitzseb  ·  3تعليقات

kolbe picture kolbe  ·  3تعليقات

goxr3plus picture goxr3plus  ·  3تعليقات