This commit is contained in:
Mn
2023-11-16 18:25:38 +08:00
parent f12a0ff25c
commit 8382129a49
4 changed files with 270 additions and 64 deletions

View File

@@ -16,47 +16,109 @@ namespace NetPanel.Bl
private string _pwd = "";
private string _host = "";
private SshClient client = null;
/// <summary>
/// 客户端
/// </summary>
private SshClient _client = null;
/// <summary>
/// sell
/// </summary>
private ShellStream _shellStream = null;
/// <summary>
/// 读取流
/// </summary>
private StreamReader _reader = null;
/// <summary>
/// 写入流
/// </summary>
private StreamWriter _writer = null;
public SshBl(string host, string username, string pwd)
/// <summary>
/// 是否连接完成
/// </summary>
private bool _isConnected = false;
/// <summary>
/// ssh连接
/// </summary>
/// <param name="host">ip</param>
/// <param name="username">登录用户</param>
/// <param name="pwd">登录密码</param>
/// <param name="columns">单元格</param>
/// <param name="rows">行</param>
/// <param name="width">宽</param>
/// <param name="height">高</param>
public SshBl(string host, string username, string pwd, uint columns, uint rows, uint width, uint height)
{
_username = username;
_pwd = pwd;
_host = host;
client = new SshClient(host, username, pwd);
client.Connect();
_client = new SshClient(host, username, pwd);
_client.Connect();
if (_client.IsConnected)
{
_shellStream = _client.CreateShellStream("xterm", columns, rows, width, height, 1024);
_reader = new StreamReader(_shellStream);
_writer = new StreamWriter(_shellStream);
}
}
/// <summary>
/// 单条读取,可循环读取
/// </summary>
/// <returns></returns>
public StreamReader RunCommand(string command)
public string ReadLine()
{
var sshCommand = client.CreateCommand(command);
var asyncExecute = sshCommand.BeginExecute();
return new StreamReader(sshCommand.OutputStream);
//string outStr;
//while ((outStr = reader.ReadLine()) != null)
//{
//}
return _reader.ReadLine();
}
public string ServerVersion()
/// <summary>
/// 写入命令
/// </summary>
/// <returns></returns>
public void WriteLine(string line)
{
return client.ConnectionInfo.ServerVersion;
_writer.WriteLine(line);
}
/// <summary>
/// 全部读取,可循环读取
/// </summary>
/// <returns></returns>
public string ReadToEnd()
{
return _reader.ReadToEnd();
}
/// <summary>
/// Ssh 客户端
/// </summary>
public SshClient Client { get { return _client; } }
/// <summary>
/// 关闭
/// </summary>
public void Dispose()
{
client.Disconnect();
client.Dispose();
if (_writer != null) _writer.Close();
if (_reader != null) _reader.Close();
//if (_shellStream != null) _shellStream.Close();
if (_shellStream != null) _shellStream.Dispose();
if (_client != null) { _client.Disconnect(); _client.Dispose(); }
}
}
}

View File

@@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using NetPanel.Bl;
using NetPanel.Help;
using Renci.SshNet;
using System.Diagnostics;
using System.Text;
namespace NetPanel.Controllers.SSH
@@ -13,10 +15,39 @@ namespace NetPanel.Controllers.SSH
public IActionResult SSH()
public async Task<IActionResult> SSH()
{
//SshBl sshBl = new SshBl("172.31.110.239", "root", "123456789");
//SshBl sshBl = new SshBl("172.29.119.239", "root", "123456789", 80, 24, 800, 600);
//var output = sshBl.ReadLine();
//sshBl.WriteLine("top");
//int cc = 0;
//while (true)
//{
// var outpu3 = sshBl.Read();
// if (cc == 0)
// {
// await Task.Delay(5000);
// sshBl.WriteLine("\x03");
// cc = 1;
// }
// else if (cc == 2)
// {
// break;
// }
//}
//sshBl.Dispose();
////string tt = sshBl.ServerVersion();
//StringBuilder sbStr = new StringBuilder();
//string tt = "";

View File

@@ -1,7 +1,13 @@
using Microsoft.AspNetCore.SignalR;
using NetPanel.Bl;
using NetPanel.Entity;
using NetPanel.Help;
using Renci.SshNet.Common;
using Renci.SshNet.Messages;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
@@ -10,6 +16,15 @@ namespace NetPanel.SignalR
public class ChatHub : Hub
{
/// <summary>
/// ssh 管理
/// </summary>
private static Dictionary<string, SshBl> dicSsh = new Dictionary<string, SshBl>();
/// <summary>
/// 建立连接时
/// </summary>
/// <returns></returns>
public override async Task OnConnectedAsync()
{
@@ -25,30 +40,114 @@ namespace NetPanel.SignalR
await client.SendAsync("ConnectionId", rm);
}
/// <summary>
/// 断开异步时
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public async Task<ReturnMsg> CreateConnectionAsync(string connectionId, string command)
public override async Task OnDisconnectedAsync(Exception? ex)
{
var cid = Context.ConnectionId;
if (dicSsh.ContainsKey(cid))
{
dicSsh[cid].Dispose();
dicSsh.Remove(cid);
}
await base.OnDisconnectedAsync(ex);
}
/// <summary>
/// 创建终端链接
/// </summary>
/// <param name="connectionId"></param>
/// <param name="command"></param>
/// <returns></returns>
public async Task<ReturnMsg> CreateConnectionAsync(uint width, uint height, uint columns, uint rows)
{
var cid = Context.ConnectionId;
ReturnMsg rm = new ReturnMsg();
rm.Code = 1;
if (!dicSsh.ContainsKey(cid))
{
SshBl ssh = new SshBl("172.29.119.239", "root", "123456789", columns, rows, width, height);
dicSsh.Add(cid, ssh);
ReceiveMessage(cid);
}
return rm;
}
/// <summary>
/// 写入命令
/// </summary>
/// <param name="curr_line"></param>
/// <returns></returns>
public async Task<ReturnMsg> WriteLineAsync(string curr_line)
{
ReturnMsg rm = new ReturnMsg();
rm.Code = 1;
//SshBl sshBl = new SshBl("172.31.110.239", "root", "123456789");
////string tt = sshBl.ServerVersion();
//StringBuilder sbStr = new StringBuilder();
//string tt = "";
//var reader = sshBl.RunCommand("top");
//string outStr = null;
//while ((outStr = reader.ReadLine()) != null)
//{
// sbStr.Append(outStr + "/r/n");
//}
rm.Obj = "====>" + command;
//根据id获取指定客户端
var client = Clients.Client(connectionId);
// await client.SendAsync("CreateConnectionAsync", rm);
var cid = Context.ConnectionId;
if (dicSsh.ContainsKey(cid))
{
dicSsh[cid].WriteLine(curr_line);
ReceiveMessage(cid);
}
return rm;
}
/// <summary>
/// 发送响应
/// </summary>
/// <param name="ssh"></param>
/// <returns></returns>
public async Task ReceiveMessage(string cid)
{
ReturnMsg rm = new ReturnMsg();
rm.Code = 1;
int count = 0;
SshBl ssh = dicSsh[cid];
//根据id获取指定客户端
var client = Clients.Client(cid);
while (true)
{
try
{
string line = ssh.ReadLine();
if (line.IsNotNull())
{
if (line.Contains(":~#"))
{
rm.Code = 2; ;
rm.Obj = line;
await client.SendAsync("ReceiveMessage", rm);
break;
}
else
{
rm.Obj = line + "\n";
await client.SendAsync("ReceiveMessage", rm);
}
}
else
{
await Task.Delay(100);
}
}
catch (Exception ex)
{
}
}
}
}
}

View File

@@ -49,8 +49,8 @@
convertEol: true, //启用时,光标将设置为下一行的开头
disableStdin: false, //是否应禁用输入。
theme: {
foreground: 'yellow', //字体
background: '#060101', //背景色
// foreground: 'yellow', //字体
// background: '#060101', //背景色
cursor: 'help',//设置光标
}
});
@@ -58,9 +58,15 @@
// 获取窗口的宽度和高度。
const width = window.innerWidth;
const height = window.innerHeight;
const columns = parseInt(width / 10);
const rows = parseInt(height / 22);
//cursorx 这个长度不能删除,用于ev.keyCode === 8
var cursorx = 0;
// 调整终端的尺寸。
term.resize(parseInt(width / 10), parseInt(height / 22));
term.resize(columns, parseInt(height / 22));
//回车输入的内容
var curr_line = '';
@@ -71,30 +77,38 @@
var connectionId = '';
term.open(document.getElementById('terminal'));
term.prompt = () => {
term.write('\n\u001b[32m$ >\u001b[37m');
};
//通讯
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
//signalR接收消息
connection.on("ReceiveMessage", function (user, message) {
term.write(message);
connection.on("ReceiveMessage", function (msg) {
term.write(msg.obj);
});
//获取通讯id
// 已建立连接
connection.on("ConnectionId", function (msg) {
term.write('Welcome to my Scheme web intepreter!\r\n123');
term.prompt();
// term.write('Welcome to my Scheme web intepreter!\r\n123');
// term.prompt();
connectionId = msg.obj;
//创建 ssh 客户端
connection.invoke('CreateConnectionAsync', width, height, columns, rows).then((result) => {
});
});
// 监听后端终端关闭
connection.on('WriteErrorAsync', () => {
@@ -104,26 +118,26 @@
term.on('key', function (key, ev) {
const printable = !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey
//const printable = !e.domEvent.altKey && !e.domEvent.altGraphKey && !e.domEvent.ctrlKey && !e.domEvent.metaKey;
if (cursorx == 0) {
cursorx = term.buffer.cursorX;
}
if (ev.keyCode === 13) { // Enter key
if (curr_line.replace(/^\s+|\s+$/g, '').length != 0) { // Check if string is all whitespace
entries.push(curr_line);
currPos = entries.length - 1;
// term.prompt();
connection.invoke('CreateConnectionAsync', connectionId, curr_line).then((result) => {
if (result.code == 1) {
//term.prompt();
//term.write(result.obj);
term.write('\n' + result.obj);
term.prompt();
connection.invoke('WriteLineAsync', curr_line).then((result) => {
if (result.code == 1) {
// term.write('\n' + result.obj);
// term.prompt();
}
});
@@ -133,7 +147,7 @@
}
curr_line = '';
} else if (ev.keyCode === 8) { // Backspace
if (term.buffer.cursorX > 3) {
if (term.buffer.cursorX > cursorx) {
curr_line = curr_line.slice(0, -1);
term.write('\b \b');
}