首页 > 解决方案 > 使用 socket.io 流式传输交互式 shell 会话

问题描述

我有 3 个组件device和.serverfrontend (admin)

服务器

使用 2 个命名空间/admin/client.
如果来自命名空间的套接字/admin发送数据,则服务器将其传递给/client命名空间。如果来自命名空间的套接字/client发送数据,则服务器将其传递给/admin命名空间。


const io = require('socket.io');
const device = io.of('/device');
const admin = io.of('/admin');

device.on('connection', (socket) => {

  socket.on('data', (data) => {
    console.log("PASSING DATA FROM [DEVICE] TO [ADMIN]")
    admin.emit('data', data);
  })

});

admin.on('connection', (socket) => {

  socket.on('data', (data) => {
    console.log("PASSING DATA FROM [ADMIN] TO [DEVICE]")
    device.emit('data', data);
  });

});

io.listen(80);

设备

用于socket.io-client连接socket.io服务器。
使用 启动交互式 shell 会话node-pty

const io = require('socket.io-client');
const socket = io('http://localhost:80/client');
const os = require('os');
const pty = require('node-pty');
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';

const ptyProcess = pty.spawn(shell, [], {
  name: 'xterm-color',
  cols: 80,
  rows: 30
});

socket.on('connect', () => {

});

// INPUT DATA
socket.on('data', (data) => {
  ptyProcess.write(data);
});

// OUTPUTING DATA
ptyProcess.onData = (data) => {
  socket.emit('data', data)
}

前端

最后,我有了用于xterm.js在浏览器中创建终端的前端。我正在使用vue. 浏览器客户端也连接到命名空间socket.io上的服务器/admin。基本上我有这个:


<template>
  <div id="app">
    <div id="terminal" ref="terminal"></div>
  </div>
</template>

<script>

import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { io } from 'socket.io-client';

export default {
  mounted() {

    const term = new Terminal({ cursorBlink : true });
    term.open(this.$refs.terminal);

    const socket = io('http://localhost:80/admin');

    socket.on('connect', () => {

      term.write('\r\n*** Connected to backend***\r\n');
      term.onData((data) => {
        socket.emit('data', data);
      })

      socket.on('data', (data) => {
        term.write(data);
      });

      socket.on('disconnect', () => {
        term.write('\r\n*** Disconnected from backend***\r\n');
      });

    });

  }
}
</script>

问题

❌ 启动 pty 会话似乎可以工作,至少现在报告了错误。然而,似乎onData侦听器回调从未被触发,即使我有ptyProcess.write()什么东西。

❌ 从一路获取输入xterm到设备ptyProcess.write似乎不起作用。我可以看到通过 socket.io 套接字一直传递到设备的数据。但从那里什么也没有发生。我想念什么?我也没有在xterm窗口中看到我的输入。

标签: node.jssocket.ioxtermjs

解决方案


从切换child_process到使用node-pty创建交互式 shell 会话后,我几乎做对了。在node-pty文档之后,它将事件处理程序标记on('data')为已弃用。相反,我应该使用.onData进程的属性来注册回调。像这样:

ptyProcess.onData =  function(data) {
  socket.emit('data', data);
};

但这并没有做任何事情。所以我切换回添加事件侦听器的过时方式:

ptyProcess.on('data', function(data) {
  socket.emit('data', data);
});

现在,我通过浏览器中的 websocket 从远程设备转发了一个有效的交互式 shell 会话✅。

更新
更多地挖掘onData财产。意识到它不是属性而是方法,所以我用错了。这将是首选方式:

ptyProcess.onData(function(data) {
  socket.emit('data', data);
});

这也可以按预期工作


推荐阅读