当前位置: 首页 > 后端技术 > Node.js

node.js+react.js+xterm.js搭建webssh

时间:2023-04-03 20:36:15 Node.js

概述先说简单的原理:前后端通信使用socket.js,后端连接服务器使用ssh2.js,页面显示控制台的操作页面,使用xterm.js。整个工作流程是:前端在xterm.js中输入文本,通过socket与后端通信,后端从前端发送命令,通过ssh2连接到服务器,获取返回的数据由服务端,通过socket传给前端,前端再显示socket返回的内容。所以这里提供几个官网,大家可以先了解一下。https://socket.io/https://github.com/staltz/xst...https://github.com/mscdex/ssh2再说说需求:我想在这里创建一个服务器,可以支持来自前端获取要连接的服务器信息,然后创建ssh2连接,页面上可以同时存在多个xterm窗口,这些窗口信息互不影响。服务器代码收到前端的createNewServer消息后,会新建一个ssh连接。为了区分不同的服务器窗口,前端必须传递一个msgId,用于向后端发送消息。然后前端可以监听不同的msgId,在不同的xterm窗口上显示socket传递过来的信息。varapp=require('express')();varhttp=require('http').Server(app);vario=require('socket.io')(http);varutf8=require('utf8');varSSHClient=require('ssh2').Client;functioncreateNewServer(machineConfig,socket){varssh=newSSHClient();let{msgId,ip,username,password}=machineConfig;ssh.on('ready',function(){socket.emit(msgId,'\r\n***'+ip+'SSH连接已建立***\r\n');ssh.shell(function(err,stream){if(err){returnsocket.emit(msgId,'\r\n***SSHSHELLERROR:'+err.message+'***\r\n');}socket.on(msgId,function(data){stream.write(data);});stream.on('data',function(d){socket.emit(msgId,utf8.decode(d.toString('binary')));}).on('close',function(){ssh.end();});})}).on('close',function(){socket.emit(msgId,'\r\n***SSH连接已关闭***\r\n');}).on('error',function(err){console.log(err);socket.emit(msgId,'\r\n***SSH连接错误:'+err.message+'***\r\n');}).connect({host:ip,port:22,username:username,password:password});}io.on('connection',function(socket){socket.on('createNewServer',function(machineConfig){//创建一个新的ssh连接console.log("createNewServer")createNewServer(machineConfig,socket);})socket.on('disconnect',function(){console.log('userdisconnected');});})http.listen(8000,function(){console.log('listeningon*8000');})front-end代码前端主要是先打开socket.io连接,点击create按钮的时候,把服务器信息和msgId传给后台,让后台可以新建一个ssh连接,然后当data在xterm窗口输入,将数据发送给服务器,并监听服务器返回的消息并显示在界面上App.jsimportReact,{Component}from'react';importlogofrom'./logo.svg';import'./App.css';importNetWorkConfigfrom"./NetWorkConfig"import"../node_modules/xterm/dist/xterm.css"import'antd/dist/antd.css';classAppextendsComponent{render(){return(

);}}导出默认应用程序;NetWorkConfig.jsximportReact从“react”从“socket.io-client”导入openSocket;从“antd”导入{Button}从“./XtermTest”导入XtermTestconstsocket=openSocket('http://localhost:8000');classNetWorkConfigextendsReact.Component{constructor(props){super(props);this.createServer1=this.createServer1.bind(this);this.createServer2=this.createServer2.bind(this);this.term1=null;this.term2=null;}createServer1(){socket.emit("createNewServer",{msgId:'net1',ip:"192.168.79.100",用户名:"lss",密码:"密码W0rd"});让term=this.term1.getTerm();term.on("data",function(data){socket.emit('net1',data);})socket.on("net1",function(data){console.log(data)term.write(data)})}createServer2(){socket.emit("createNewServer",{msgId:'net2',ip:"192.168.79.100",用户名:"lss",密码:"PassW0rd"});让term=this.term2.getTerm();term.on("data",function(data){socket.emit('net2',data);})socket.on("net2",function(data){term.write(data)})}render(){return
按钮1按钮2{this.term1=term1}}id="net1"/>{this.term2=term2}}id="net2"/>
}}exportdefaultNetWorkConfigXtermTest.jsximportReactfrom"react"import{Terminal}from'xterm';import*asfitfrom'../node_modules/xterm/dist/addons/fit/fit';classXtermTestextendsReact.Component{constructor(props){super(props)this.getTerm=this.getTerm.bind(this);}}render(){return
}getTerm(){returnthis.term;}componentDidMount(){Terminal.applyAddon(fit);让{id}=this.props;让terminalContainer=document.getElementById(id);this.term=newTerminal({cursorBlink:true});这个.term.open(terminalContainer);这个.term.fit();}}exportdefaultXtermTest启动指令首先node启动server.js,然后正常启动react项目还是比较粗糙的版本。效果如图:点击按钮1时初始化第一个窗口,点击按钮2时初始化第二个窗口。因为传递的是不同的msgId,两个窗口之间不会有信息干扰。