xterm.js+react+websoket实现终端功能xterm 4.x(含jquery版本)

6,971 阅读3分钟

最近工作有个需求,需要在web端实现一个远程连接终端操作的类似网页版xshell的实现。实现界面如下图。

需求:输入用户名密码,跟后台验证登陆,然后跟后端进行命令行通信。

开始做的时候,就选了xterm,然后照着一些demo写,结果遇到很多坑。

1.xterm版本不同,方法不同

xterm4.x应该是在2019月份就开始更新了,但现在网上用的大多数的版本还都是3.x。网上很多例子都是3.x的。开始没注意到,结果调用方法报undefined错误。一脸懵圈。

2.xterm没有详细的文档说明,有英文文档,也只有简单的几个例子。

官方文档地址:xtermjs.org/  虽然文档不全,但是有还是比没有好。

3.我们自己的系统问题也挺多的。所以遇到一些问题,不知道是与现有的冲突,还是我没写对。总之探索的过程很煎熬。

文档

安装

npm install xterm    //现在版本是4.8.1   安装xterm
npm install xterm-addon-fit    // xterm 插件,让xterm适应外部样式

初始化

import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import '../node_modules/xterm/css/xterm.css'   //如果你的xterm样式乱了,需要调整这个路径
//我后来是直接把这个css  copy到项目目录下进行引用
//定义xterm的外观  具体看xterm文档
const term = new Terminal({  
rendererType: 'canvas',  
cursorBlink: true,  
convertEol: true,  
scrollback: 800,  
row: 70,  
theme: {    
foreground: 'white',    
background: '#181E29'  
}})

const fitAddon = new FitAddon();    
term.loadAddon(fitAddon);    
fitAddon.fit();    
term.open(document.getElementById('terminal'));  //绑定dom节点    
term.writeln('Connecting...');

原理

前端和后端的通信,使用的是WebSocket,后端连接服务器,我只负责前端部分,所以这里只列前端的方法。页面显示出控制台这个操作页面,使用的是xterm.js。整个工作流程就是:前端在xterm.js里面输入文字,通过socket和后端通信,后端把前端传过来的命令,通过ssh连接服务器,得到服务器返回的数据,通过socket传给前端,前端再显示出socket返回的内容。

之前走了一些弯路,网上很多帖子用socket.io-client这个插件,但是我装了以后,并不好用,后来发现xterm官网有现成的 ,xtermjs.org/docs/api/ad…

import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';

const term = new Terminal();
const socket = new WebSocket('wss://docker.example.com/containers/mycontainerid/attach/ws');
const attachAddon = new AttachAddon(socket);

// Attach the socket to term
term.loadAddon(attachAddon);

通信

let socket = new WebSocket('ws://192.168.3.155:8008/webssh');//地址

//输入内容 将内容传给服务器
  term.onKey(e => {      
// term.write(e.key);      
// console.log(e.key)      
socket.send(JSON.stringify({ "operate": "command", "command": e.key, module: "webssh" }));    })

const operate = {      onError: function (error) {        //连接失败回调        term.write('Error: ' + error + '\r\n');      },      onConnect: function () {        //连接成功回调        socket.send(JSON.stringify(option))  //连接成功的回调      },      onClose: function () {        //连接关闭回调        term.write("\rconnection closed");      },      onData: function (data) {        //收到数据时回调        term.write(data);        term.focus()      }    }

  if (window.WebSocket) {      //如果支持websocket      // this._connection = new WebSocket(endpoint);      console.log("good!!!")    } else {      //否则报错      operate.onError('WebSocket Not Supported');      return;    }    //连接成功    socket.onopen = function () {      operate.onConnect()    };    socket.onmessage = function (evt) {      let data = evt.data.toString();      //data = base64.decode(data);      console.log("data", data)      operate.onData(data);    };    socket.onclose = function (evt) {      operate.onClose();    };  }

demo

github:github.com/hourong88/x…

npm install
npm start

另外还有jquery版本demo

github:github.com/hourong88/x…

参考文章