react?express實(shí)現(xiàn)webssh?demo解析
正文
下面是一個(gè)簡(jiǎn)單的 WebSSH Demo,實(shí)現(xiàn)了通過(guò)瀏覽器連接 SSH 服務(wù)器并進(jìn)行交互的功能。
實(shí)現(xiàn) WebSSH 的基本思路
WebSSH 可以分成以下幾個(gè)模塊:
- 前端界面:使用 xterm.js 實(shí)現(xiàn)一個(gè)基于瀏覽器的終端界面。
- WebSocket 連接:使用 WebSocket 連接連接 WebSSH 服務(wù)器后端。
- SSH 連接:使用 ssh2.js 庫(kù)連接 SSH 服務(wù)器,然后在 WebSocket 和 SSH 之間建立一個(gè)雙向通訊。
實(shí)現(xiàn) Demo 的代碼
服務(wù)器端代碼
服務(wù)器端代碼使用 Node.js 和 WebSocket 模塊實(shí)現(xiàn),主要用于連接到遠(yuǎn)程 SSH 服務(wù)器并與前端建立 WebSocket 連接。
const SSHClient = require('ssh2').Client; const utf8 = require('utf8'); export const createNewServer = (machineConfig: any, socket: any) => { const ssh = new SSHClient(); const { host, username, password } = machineConfig; // 連接成功 ssh.on('ready', function () { socket.send('\r\n*** SSH CONNECTION SUCCESS ***\r\n'); ssh.shell(function (err: any, stream: any) { // 出錯(cuò) if (err) { return socket.send('\r\n*** SSH SHELL ERROR: ' + err.message + ' ***\r\n'); } // 前端發(fā)送消息 socket.on('message', function (data: any) { stream.write(data); }); // 通過(guò)sh發(fā)送消息給前端 stream.on('data', function (d: any) { socket.send(utf8.decode(d.toString('binary'))); // 關(guān)閉連接 }).on('close', function () { ssh.end(); }); }) // 關(guān)閉連接 }).on('close', function () { socket.send('\r\n*** SSH CONNECTION CLOSED ***\r\n'); // 連接錯(cuò)誤 }).on('error', function (err: any) { socket.send('\r\n*** SSH CONNECTION ERROR: ' + err.message + ' ***\r\n'); // 連接 }).connect({ port: 22, host, username, password }); }
前端代碼
前端代碼主要包括一個(gè)包裝 xterm.js 的 React 組件和一些 WebSockets 相關(guān)的代碼。
import React, { useEffect, useRef } from 'react'; import { Terminal } from 'xterm'; import { WebLinksAddon } from 'xterm-addon-web-links'; import { FitAddon } from 'xterm-addon-fit'; import 'xterm/css/xterm.css'; const FontSize = 14; const Col = 80; const WebTerminal = () => { const webTerminal = useRef(null); const ws = useRef(null); useEffect(() => { // 初始化終端 const ele = document.getElementById('terminal'); if (ele && !webTerminal.current) { const height = ele.clientHeight; // 初始化 const terminal = new Terminal({ cursorBlink: true, cols: Col, rows: Math.ceil(height / FontSize), }); // 輔助 const fitAddon = new FitAddon(); terminal.loadAddon(new WebLinksAddon()); terminal.loadAddon(fitAddon); terminal.open(ele); terminal.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ '); fitAddon.fit(); webTerminal.current = terminal; } // 初始化ws連接 if (ws.current) ws.current.close(); const socket = new WebSocket('ws://localhost:3001'); socket.onopen = () => { socket.send('connect success'); }; ws.current = socket; }, []); useEffect(() => { // 新增監(jiān)聽(tīng)事件 const terminal = webTerminal.current; const socket = ws.current; if (terminal && socket) { // 監(jiān)聽(tīng) terminal.onKey(e => { const { key } = e; socket.send(key); }); // ws監(jiān)聽(tīng) socket.onmessage = e => { console.log(e); if (typeof e.data === 'string') { terminal.write(e.data); } else { console.error('格式錯(cuò)誤'); } }; } }, []); return <div id="terminal" style={{ backgroundColor: '#000', width: '100vw', height: '100vh' }}/>; }; export default WebTerminal;
WebSSH 組件借助 Hooks 特性進(jìn)行 WebSocket 和 xterm.js 的初始化。具體來(lái)說(shuō),這個(gè)組件使用了 useEffect Hook 在組件掛載時(shí)完成以下工作:
- 初始化 Terminal 組件。
- 初始化 WebSocket 連接。
- 為 Terminal 組件綁定輸入事件和 WebSocket 發(fā)送數(shù)據(jù)的邏輯。
在 React 應(yīng)用中使用 WebSSH 組件
你需要在你的 React的index.js 文件中引入 WebSSH 組件,并在你的應(yīng)用中渲染它:
import WebSSH from './components/WebSSH'; import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <WebSSH />, document.getElementById('root') );
效果
編輯
總結(jié)
在本篇博客中,我們學(xué)習(xí)了如何使用 xterm.js、WebSocket 和 ssh2.js 庫(kù)構(gòu)建一個(gè) WebSSH 應(yīng)用程序。我們創(chuàng)建了一個(gè)簡(jiǎn)單的 Demo 來(lái)演示該過(guò)程。
完整代碼參考
GitHub - judithhuang/webssh-demo
以上就是react express實(shí)現(xiàn)webssh demo解析的詳細(xì)內(nèi)容,更多關(guān)于react express實(shí)現(xiàn)webssh的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
每天一個(gè)hooks學(xué)習(xí)之useUnmount
這篇文章主要為大家介紹了每天一個(gè)hooks學(xué)習(xí)之useUnmount,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05react裝飾器與高階組件及簡(jiǎn)單樣式修改的操作詳解
這篇文章主要介紹了react裝飾器與高階組件及簡(jiǎn)單樣式修改的操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09React組件設(shè)計(jì)過(guò)程之仿抖音訂單組件
這篇文章主要介紹了React組件設(shè)計(jì)過(guò)程之仿抖音訂單組件的實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07如何解決React官方腳手架不支持Less的問(wèn)題(小結(jié))
這篇文章主要介紹了如何解決React官方腳手架不支持Less的問(wèn)題(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09React中使用Echarts無(wú)法顯示title、tooltip等組件的解決方案
這篇文章主要介紹了React中使用Echarts無(wú)法顯示title、tooltip等組件的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03React經(jīng)典面試題之倒計(jì)時(shí)組件詳解
這些天也都在面試,面試的內(nèi)容也大多千篇一律,無(wú)外乎vue、react這些框架的一些原理,和使用方法,但是也遇到些有趣的題目,這篇文章主要給大家介紹了關(guān)于React經(jīng)典面試題之倒計(jì)時(shí)組件的相關(guān)資料,需要的朋友可以參考下2022-03-03