首页 > 系统相关 >Flask 学习100-Flask-SocketIO 结合 xterm.js 实现网页版Xshell

Flask 学习100-Flask-SocketIO 结合 xterm.js 实现网页版Xshell

时间:2024-02-20 20:55:09浏览次数:32  
标签:__ socket socketio Flask xterm namespace SocketIO message data

前言

xterm.js 是一个使用 TypeScript 编写的前端终端组件,可以直接在浏览器中实现一个命令行终端应用。
可以实现 web-terminal 功能,类似于Xshell 操作服务器。
Flask-SocketIO 快速入门与使用基础参考前面这篇https://www.cnblogs.com/yoyoketang/p/18022139

前后端交互

前端代码
io.connect 连上服务端
socket.emit 给后端发送消息
socket.on('response', ) 监听服务端返回的数据

<!DOCTYPE html>
<html>
<head>
    <title>web</title>
    <meta charset="UTF-8">
    <script type="text/javascript" src="/static/jquery-3.5.1.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
</head>

<body>
<script type="text/javascript" charset="UTF-8">
    $(document).ready(function() {
        const namespace = '/ws'
        // 连上服务器
        const socket = io.connect("http://" + document.domain + ":" + location.port + namespace);

        // 发送message 消息
        socket.emit("message",{"data":"hello world!"});

        // 收到数据后,执行输出
        socket.on('response', function(recv) {
            console.log('hello: ' + recv.data)
        });
    });
</script>
</body>
</html>

flask 后端代码

from flask import Flask, render_template,request
from flask_socketio import SocketIO



app = Flask(import_name=__name__,
            static_url_path='/static',   # 配置静态文件的访问url前缀
            static_folder='static',      # 配置静态文件的文件夹
            template_folder='templates') # 配置模板文件的文件夹

app.config['SECRET_KEY'] = "abcdef"
socketio = SocketIO(app)


@app.route("/")
def index():
    return render_template("web.html")


# 出现消息后,率先执行此处
@socketio.on("message", namespace="/ws")
def socket(message):
    print(f"接收到消息: {message['data']}")
    for i in range(1, 10):
        socketio.sleep(1)
        socketio.emit("response",           # 绑定通信
                      {"data": i},           # 返回socket数据
                      namespace="/ws")


# 当websocket连接成功时,自动触发connect默认方法
@socketio.on("connect", namespace="/ws")
def connect():
    print("链接建立成功..")


# 当websocket连接失败时,自动触发disconnect默认方法
@socketio.on("disconnect", namespace="/ws")
def disconnect():
    print("链接建立失败..")


if __name__ == '__main__':
    socketio.run(
        app,
        debug=True,
        host="0.0.0.0",
        port=8000,
        allow_unsafe_werkzeug=True
    )

基本代码调通后,再去实现一个WebSSH终端就会变得很容易, web-terminal终端我们需要xterm.js这个前端库来实现,

xterm.js 实现网页版终端

前端实现
io.connect 连上服务端
socket.emit 给后端发送消息
socket.on('response', ) 监听服务端返回的数据
term.onData 监听terminal终端上输入的数据

<!DOCTYPE html>
<html>
<head>
    <title>web</title>
    <meta charset="UTF-8">
    <script type="text/javascript" src="/static/jquery-3.5.1.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="/static/bootstrap.min.css">
    <!-- 引入 xterm 的 CSS 文件 -->
    <link rel="stylesheet" href="/static/xterm.css">
    <!-- 引入 xterm 的 JavaScript 文件 -->
    <script src="/static/xterm.js"></script>


</head>
<body>
    <div id="terminal"></div>
    <script>
        const window_width = $(window).width();
        const window_height = $(window).height();
        const term = new Terminal(
            {
                cols: Math.floor(window_width / 9),
                rows: Math.floor(window_height / 9),
                useStyle: false,
                convertEol: true, //启用时,光标将设置为下一行的开头
                cursorBlink: true,
                // disableStdin: false, //是否应禁用输入。
                cursorStyle: null, //光标样式
                // theme: {
                //      foreground: 'yellow', //字体
                //      background: '#060101', //背景色
                //      cursor: 'help'//设置光标
                //  }
            }
        )
        console.log("高度" + window_height + "宽度" + window_width);

        $(document).ready(function() {
            // 连接服务器
            const namespace = '/ws';
            const socket = io.connect("http://" + document.domain + ":" + location.port + namespace);

            socket.on("connect", function(){
                // 打开终端
                term.open(document.getElementById('terminal'));
            });

            // 接受后端数据,并写到控制台
            socket.on("response", function(recv){
                term.write(recv.data);
            });

            // terminal终端上输入的数据发送消息到服务端
            term.onData((data) => {
              console.log('发送消息:'+data)
              socket.send(data);
              // socket.emit('message', {"data":data});
            });
        });
</script>
</body>
</html>

这里有个坑,之前看到其他人写的是term.on, 是比较老的xterm.js语法

           // 发送消息到对端
            term.on("data",function(data){
               socket.send(data);
               //socket.emit("message",{"data":data});
            });

最新的xterm.js语法改成term.onData了

            // terminal终端上输入的数据发送消息到服务端
            term.onData((data) => {
              console.log('发送消息:'+data)
              socket.send(data);
              // socket.emit('message', {"data":data});
            });

flask 后端代码实现

from flask import Flask, render_template, request
from flask_socketio import SocketIO
import paramiko

app = Flask(import_name=__name__,
            static_url_path='/static',    # 配置静态文件的访问url前缀
            static_folder='static',       # 配置静态文件的文件夹
            template_folder='templates')  # 配置模板文件的文件夹

app.config['SECRET_KEY'] = "abcdef"
socketio = SocketIO(app)


def ssh_cmd():
    tran = paramiko.Transport(('192.1.1.x', 22,))
    tran.start_client()
    tran.auth_password('root', 'aa*******')
    chan = tran.open_session()
    chan.get_pty(height=492, width=1312)
    chan.invoke_shell()
    return chan


sessions = ssh_cmd()


@app.route("/")
def index():
    return render_template("web.html")


@socketio.on("message", namespace="/ws")
def socket(message):
    """接收到前端message消息,执行此方法"""
    print(f"接收到消息: {message}")
    sessions.send(message)  # 传到服务器上执行
    ret = sessions.recv(4096)
    socketio.emit(
        "response",
        {"data": ret.decode("utf-8")},
        namespace="/ws"
    )


@socketio.on("connect", namespace="/ws")
def connect():
    """当websocket连接成功时,自动触发connect默认方法"""
    ret = sessions.recv(4096)
    socketio.emit(
        "response",
        {"data": ret.decode("utf-8")},
        namespace="/ws")
    print("链接建立成功..")


@socketio.on("disconnect", namespace="/ws")
def disconnect():
    """当websocket连接失败时,触发disconnect默认方法"""
    print("链接建立失败..")


if __name__ == '__main__':
    socketio.run(
        app,
        debug=True,
        host="0.0.0.0",
        port=8000,
        allow_unsafe_werkzeug=True
    )

浏览器打开web网页地址就能看到连接服务器成功

于是一个简单的网页版xshell就可以实现了

参考学习相关博客
Flask 框架:运用SocketIO实现WebSSH https://www.bmabk.com/index.php/post/159498.html
用 xterm.js 实现一个简易的 web-terminal ! https://juejin.cn/post/6918911964009725959

标签:__,socket,socketio,Flask,xterm,namespace,SocketIO,message,data
From: https://www.cnblogs.com/yoyoketang/p/18022839

相关文章

  • Flask 学习99-Flask-SocketIO 开发websocket接口
    前言flask-socketio为flask应用提供了一个客户端与服务器之间低延迟的双向通讯官网地址:https://flask-socketio.readthedocs.io/en/latest/intro.html环境准备先安装flask-socketiopipinstallflask-socketio说明Flask-SocketIO与js版本客户端不匹配,二者不能正常通信。......
  • python - flask wsgi
    直接使用flask自带的wsgi,关闭debug模式会出现以下警告fromflaskimportFlaskapp=Flask(__name__,static_folder="./static")app.run(host="0.0.0.0",port=8080,debug=False)#WARNING:Thisisadevelopmentserver.Donotuseitinaproductiondeployme......
  • 无涯教程-Flask - 应用程序
    为了测试Flask的安装,在编辑器中以Hello.py键入以下代码fromflaskimportFlaskapp=Flask(__name__)@app.route('/')defhello_world():return'HelloWorld'if__name__=='__main__':app.run()必须在项目中导入Flask模块。Flask类的对象是无涯教程的WSG......
  • 无涯教程-Flask - 环境设置
    安装Flask通常需要Python2.6或更高版本,尽管Flask及其依赖项在Python3(Python3.3及更高版本)上可以很好地工作,但是许多Flask扩展都无法正确地支持它,因此,建议在Python2.7上安装Flask。使用virtualenv安装virtualenv是一个虚拟的Python环境构建器。它可以帮助用户并行创建多......
  • Flask框架之request参数
    一、Flask框架之request对象    浏览器访问服务端,向服务端发送请求数据,可通过以下方式:通过URL参数进行查询,浏览器需要将查询参数发给服务器;浏览器提交form表单数据给到服务器端上传文件,浏览器将文件数据发给服务器端   服务端接收到浏览器发送的请求,封装到fla......
  • flask-study-005
    本篇博客记录flask-mail的使用fromflaskimportFlaskfromflask_mailimportMail,Messageapp=Flask(__name__)app.config['MAIL_SERVER']='smtp.163.com'app.config['MAIL_PORT']='465'app.config['MAIL_USE_TLS'......
  • Flask : GET-POST
    fromflaskimportFlask,request,jsonifyfromflask_restfulimportApi,Resource,reqparseapp=Flask(__name__)api=Api(app)####--GET请求参数--传递参数到GET请求中#####1.GET传递查询字符串参数#URL进行GET请求:http://localhost:5000/users?......
  • Django学习第一天-Flask_Web前端HTML部分
    目录1.day11.快速开发网站2.浏览器能识别的标签2.1编码2.2title2.3标题2.4div和span2.5超链接2.6图片小结2.7列表2.8表格2.9input系列(7个)2.10下拉框2.11多行文本案例:用户注册2.12网络请求目的:开发一个平台(网站)-前端开发:HTML、CSS、JavaScript-Web框架:接收并处理请求......
  • linux CentOS MobaXterm 通过X11 Forwarding 在本地开启图形可视化窗口
    第一步操作系统安装图形界面X11Forwardingdnfinstallxorg-x11-xauthxorg-x11-fonts-*xorg-x11-font-utilsxorg-x11-fonts-Type1xclock1第二步修改参数,启用X11Forwardingvim/etc/ssh/sshd_config1修改参数X11Forwardingyes和X11UseLocalhostno#AllowAgentForwarding......
  • socketioxide 基于rust 的socket.io server 实现
    socketioxide是基于rust的socket.ioserver实现包含的特性类似axum的API完全兼容官方socket.ioclient支持v4协议状态管理namespacesrooms消息确认polling以及websocket支持说明目前socketioxide实际上也支持adapter,支持是本地的,缺少集群模式的支持,比如nodej......