node.js+react.js+xterm.js构建webssh - 个人文章 - SegmentFault 思否


本站和网页 https://segmentfault.com/a/1190000017835511 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

node.js+react.js+xterm.js构建webssh - 个人文章 - SegmentFault 思否注册登录问答专栏标签招聘活动发现✓使用“Bing”搜本站使用“Google”搜本站使用“百度”搜本站站内搜索注册登录node.js+react.js+xterm.js构建websshsupportlss2272关注作者首页专栏node.js文章详情5node.js+react.js+xterm.js构建websshsupportlss2272发布于2019-01-10  
概述
先讲一下简单的原理:前端和后端的通信,使用的是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,将socket传递过来的信息显示到不同的xterm窗口上。
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var utf8 = require('utf8');
var SSHClient = require('ssh2').Client;
function createNewServer(machineConfig, socket) {
var ssh = new SSHClient();
let {msgId, ip, username, password} = machineConfig;
ssh.on('ready', function () {
socket.emit(msgId, '\r\n***' + ip + ' SSH CONNECTION ESTABLISHED ***\r\n');
ssh.shell(function(err, stream) {
if(err) {
return socket.emit(msgId, '\r\n*** SSH SHELL ERROR: ' + 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 CONNECTION CLOSED ***\r\n');
}).on('error', function (err) {
console.log(err);
socket.emit(msgId, '\r\n*** SSH CONNECTION ERROR: ' + 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('user disconnected');
});
})
http.listen(8000, function() {
console.log('listening on * 8000');
})
前端代码
前端主要是先打开socket.io连接,在点击创建按钮的时候,把服务器的信息和msgId传递给后台,让后台能够创建一个新的ssh连接,然后在xterm窗口输入数据的时候,把数据发送给服务端,并且监听服务器返回的消息显示到界面上来。App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import NetWorkConfig from "./NetWorkConfig"
import "../node_modules/xterm/dist/xterm.css"
import 'antd/dist/antd.css';
class App extends Component {
render() {
return (
<div className="App">
<NetWorkConfig/>
</div>
);
export default App;
NetWorkConfig.jsx
import React from "react"
import openSocket from 'socket.io-client';
import {Button} from "antd"
import XtermTest from "./XtermTest"
const socket = openSocket('http://localhost:8000');
class NetWorkConfig extends React.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", username: "lss", password: "PassW0rd"});
let 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", username: "lss", password: "PassW0rd"});
let term = this.term2.getTerm();
term.on("data", function(data) {
socket.emit('net2', data);
})
socket.on("net2", function (data) {
term.write(data)
})
render() {
return <div>
<Button onClick={this.createServer1}>按钮1</Button>
<Button onClick={this.createServer2}>按钮2</Button>
<XtermTest ref={(term1) => {this.term1 = term1}} id="net1"/>
<XtermTest ref={(term2) => {this.term2 = term2}} id="net2"/>
</div>
export default NetWorkConfig
XtermTest.jsx
import React from "react"
import { Terminal } from 'xterm';
import * as fit from '../node_modules/xterm/dist/addons/fit/fit';
class XtermTest extends React.Component {
constructor(props) {
super(props)
this.getTerm = this.getTerm.bind(this);
render() {
return <div id={this.props.id}></div>
getTerm() {
return this.term;
componentDidMount() {
Terminal.applyAddon(fit);
let {id} = this.props;
let terminalContainer = document.getElementById(id);
this.term = new Terminal({cursorBlink: true});
this.term.open(terminalContainer);
this.term.fit();
export default XtermTest
启动说明
先node启动server.js,然后再正常启动react工程。目前还是一个比较粗糙的版本。效果如图:点击按钮1的时候初始化第一个窗口,点击按钮2的时候初始化第二个窗口。因为传递了不同的msgId,两个窗口不会有信息的干扰。
react.jsnode.js阅读 9.9k更新于 2019-01-10 赞5收藏1分享本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议supportlss227 声望16 粉丝关注作者0 条评论得票最新提交评论评论支持部分 Markdown 语法:**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用 @ 来通知其他用户。推荐阅读nodejs-buffer: 基础篇概念 buffer存了什么 buffer是一个操作字节的对象,它的底层是一个字节数组,存储着16进制数字。 {代码...} buffer的每个元素是16进制的两位数,也就是每个元素的大小是0-255. 因为 F X 16 + F X 16^0 = 255 溢出...supportlss阅读 1.3k一个被忽略的前端细分领域大家好,我卡颂。回想下你学新技术的主要途径是什么?看书?看技术文档?看博文?看视频?归纳起来,无外乎文字、视频两种形式。从纸媒时代到互联网时代,再到移动互联网时代,虽然信息的载体发生变化,但信息的...卡颂赞 18阅读 1.5k「彻底弄懂」this全面解析当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在 哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在 函数执行的过程中用到...wuwhs赞 14阅读 1.6k给我实现一个前端的 Excel 导入和导出功能前言【负责人 A】:现在报表部分基于接口的 Excel 的导入和导出功能有点慢,前端这边能不能实现一下这个功能,然后我们在比对看看效果!【切图仔 B】: 接口这边不能优化一下吗?比如排查下慢的原因什么的。【负...熊的猫赞 16阅读 2.1k一个开源vue网站博客,nuxt开源网站,前后端分离项目开媛笔记,基于nuxt ssr首屏服务器端渲染 。用于分享、记录、交流和学习,希望可以帮助到小伙伴们。同时网站在不断更新,创造属于猿(媛)的世界 -$Bao Yalong ..Let's Go! [链接]jigsaw赞 16阅读 8.2k评论 3SegmentFault 思否技术周刊 Vol.45 -- 进击的 React React 是一个免费的开放源代码前端 JavaScript 工具库, 用于基于 UI 组件构建用户界面。 它由 Meta 和一个由个人开发者和公司组成的社群维护。 React 可用作开发具有 Next.js 等框架的单页、手机或服务器渲染应...Beverly赞 11阅读 3.1k2022 你还不会微前端吗 (上) — 从巨石应用到微应用微前端系列分为 上/下 两篇,本文为 上篇 主要还是了解微前端的由来、概念、作用等,以及基于已有的微前端框架进行实践,并了解微前端的核心功能所在,而在下篇 2022 你还不会微前端吗 (下) — 揭秘微前端核心原理...熊的猫赞 14阅读 1.3ksupportlss227 声望16 粉丝关注作者宣传栏文章目录跟随▲51产品热门问答热门专栏热门课程最新活动翻译酷工作课程Java 开发课程PHP 开发课程Python 开发课程前端开发课程移动开发课程资源每周精选用户排行榜帮助中心建议反馈合作关于我们广告投放职位发布讲师招募联系我们合作伙伴关注产品技术日志社区运营日志市场运营日志团队日志社区访谈条款服务协议隐私政策下载 AppCopyright © 2011-2022 SegmentFault. 当前呈现版本 22.12.19浙ICP备15005796号-2浙公网安备33010602002000号ICP 经营许可 浙B2-20201554杭州堆栈科技有限公司版权所有