You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SSH.NET库无法读取SSH服务器响应的问题排查求助

排查思路与解决建议

1. 明确设备SSH服务的交互模式

很多专用设备的SSH服务并非标准POSIX shell环境,而是自定义的命令交互接口:

  • CreateCommand依赖标准shell的fork/exec机制执行命令,这类设备不支持该模式,会导致命令执行后无法返回(无限挂起)。
  • Putty连接后直接进入交互会话,说明设备SSH基于伪终端(PTY)的交互模式,而非标准命令执行通道。

2. 优化ShellStream的交互逻辑

当前ShellStream的读取逻辑存在缺陷,需匹配设备的交互格式调整:

修正命令发送的换行符

设备的Telnet/HTTP接口用VERSION?即可,但SSH交互可能仅识别特定换行符(比如部分设备只认\r而非默认的\r\n),修改发送代码:

// 替换WriteLine,直接发送带正确换行符的命令
shellStream.Write(sendStr + "\r");
shellStream.Flush();

改进读取逻辑,过滤无效字符

设备返回的\r\0属于终端控制字符,需读取完整输出并过滤:

StringBuilder responseBuilder = new StringBuilder();
DateTime startTime = DateTime.Now;
// 设置超时避免无限等待
while (DateTime.Now - startTime < TimeSpan.FromSeconds(5))
{
    if (shellStream.DataAvailable)
    {
        string chunk = shellStream.Read();
        // 过滤空字符和无效控制符
        chunk = chunk.Replace("\0", "").Trim();
        if (!string.IsNullOrEmpty(chunk))
        {
            responseBuilder.Append(chunk);
            // 检查是否到达响应结束标记(比如设备命令响应后会回到提示符)
            if (responseBuilder.ToString().EndsWith(">") || responseBuilder.ToString().EndsWith("#"))
            {
                break;
            }
        }
    }
    await Task.Delay(20);
}
string finalResponse = responseBuilder.ToString().Trim();

3. 匹配Putty的终端交互细节

Putty连接时会发送特定的终端协商参数,需调整SSH.NET的CreateShellStream参数:

  • 尝试更换终端类型(比如用ansi替代vt100)
  • 关闭终端回声(避免设备回显命令导致读取到重复内容)
// 调整终端类型
shellStream = sshClient.CreateShellStream("ansi", 80, 24, 800, 600, 4096);
// 发送命令关闭回声(不同设备命令可能不同,如stty -echo)
shellStream.Write("stty -echo\r");
shellStream.Flush();
// 读取并丢弃回声关闭后的响应
await Task.Delay(100);
if (shellStream.DataAvailable) shellStream.Read();

4. 抓包对比交互流程

用Wireshark抓取Putty和SSH.NET的SSH交互报文,重点对比:

  • Putty连接后发送的终端协商参数(TERM环境变量、窗口大小、控制选项)
  • 命令发送的换行符类型
  • 设备响应的格式和结束标记
    根据抓包结果调整SSH.NET的参数和交互逻辑。

5. 尝试直接使用SSH底层通道

如果ShellStream仍有问题,可跳过PTY模拟,直接创建SSH会话通道:

var channel = sshClient.CreateChannel<ChannelSession>();
channel.Open();
// 发送命令(带正确换行符)
channel.SendData(Encoding.ASCII.GetBytes(sendStr + "\r"));
// 读取响应
byte[] buffer = new byte[4096];
StringBuilder response = new StringBuilder();
while (channel.DataAvailable)
{
    int bytesRead = channel.Receive(buffer);
    response.Append(Encoding.ASCII.GetString(buffer, 0, bytesRead));
    await Task.Delay(50);
}
channel.Close();
string result = response.ToString().Trim();

内容的提问来源于stack exchange,提问作者JimJamFlimFlam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:00:14