1

我正在写一个网络终端来玩。我正在使用 xterm js + pty。我有一个 linux 服务器,客户端使用 websocket 连接到它。websocket 将向服务器发送消息,该消息将发送到由 pty 生成的终端。任何输出都将通过 websocket 发送回 xterm 中的客户端。一切正常。

但是在不稳定的网络中,我想在断开连接后重新连接websocket。这是我的处理方式。

function createWebSocket() {
  var socket = new WebSocket(socketUri);
  socket.onopen = handleSocketOpen;
  socket.onclose = handleSocketClose;
}

function handleSocketClose() {
  term.writeln("\n\r\x1B[1;31mTerminal was disconnected.\x1B[0m ");
  retryConnectClosedSocketOrCleanup(1);
}


    function retryConnectClosedSocketOrCleanup(retryCount) {
      // Get current term size.
      var method = 'POST';
      var geometry = term.proposeGeometry();
      var targetUri = consoleUri + '/terminals/' + termId + '/size?cols=' + geometry.cols + '&rows=' + geometry.rows;

      // Resize terminal to detect if the terminal exists on the server.
      $.ajax(targetUri,
        {
          method: method,
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
          },
          timeout: 3000
        })
        .fail(function (jqXHR, textStatus, errorThrown) {

          // If resize failed with 4xx or 5xx, then there is no way to reconnect to the same terminal.
          // Do socket close clean up right away.
          if (jqXHR.status >= 400) {
            console.warn("Terminal failed to reconnect because the previous session no longer exists.");
            socketCloseCleanup();
            return;
          }

          // If resize failed with other reason, retry.
          retryCount = retryCount || 0;
          if (retryCount > maxRetrySocketConnectionCount) {
            term.writeln("\n\r\x1B[1;31mTerminal failed to reconnect after " + maxRetrySocketConnectionCount + " attempts. \x1B[0m");
            socketCloseCleanup();
          } else {
            term.write(retryCount == 1 ? "\n\r\x1B[1;31mReconnecting terminal.." : "\x1B[1;31m.");
            setTimeout(function () { retryConnectClosedSocketOrCleanup(retryCount + 1) }, retrySocketConnectionDelay);
          }
        })
        .done(function (data, textStatus, jqXHR) {
          // If resize was successful, then the terminal still exists on the server.
          // Reopen socket.
          if (jqXHR.status === 200) {
            term.writeln("\x1B[1;32m Terminal reconnected.\x1B[0m ");
            term.fit();
            term.clear();
            term.eraseLine(0);
            createWebSocket();
          }
        });
    }

在大多数情况下它也可以正常工作。但是,一旦我使用“vi”或“vim”,任何后续的重新连接都会导致最后出现一些奇怪的字符。

在此处输入图像描述

我用谷歌搜索了很多,但没有找到太多。我唯一发现的是here,它看起来像是来自termcap 的一堆错误响应。

跟进: 我发现问题实际上来自客户端的 xterm js。这是我所做的:

我将 console.log 添加到 xterm js attach 插件,以查看是否是 xterm js 在重新连接后首先将这些字符发送到服务器。结果是“是的”。请参阅控制台日志。

在此处输入图像描述

打开vim后,我断开了互联网。此日志在重新连接后立即出现。如您所见,终端(xterm js Terminal 对象)首先使用这些字符发送到套接字,然后通过套接字从服务器接收到相同的内容。我搜索了 xterm js 的代码库,看起来这些字符是从https://github.com/sourcelair/xterm.js/blob/42724c7f42f827d9e247d461066eb1506725e371/src/Parser.ts#L526-L535生成的。

任何想法?

4

0 回答 0