如何判断TScSSHShell的ScSSHShellAsyncReceive完成远程数据接收?
解决方案:判断TScSSHShell异步接收数据完成的方法
核心思路
思科、SRX等网络设备执行命令后,会在输出末尾返回命令提示符(比如Router#、root@srx> ),这是判断接收完成的关键标识。通过在OnAsyncReceive事件中累积接收的数据,并检查是否包含预设的提示符,即可确定数据是否接收完毕。
具体实现步骤
1. 定义类级变量
在窗体或数据模块中定义变量,用于累积数据、存储目标提示符和标记接收状态:
private FReceivedData: string; FExpectedPrompt: string; // 当前命令对应的设备提示符 FIsReceiving: Boolean; // 标记是否处于命令接收状态
2. 执行命令前的初始化
调用WriteString发送命令前,初始化变量并记录当前设备的提示符(可提前通过登录交互获取,或手动指定):
// 示例:执行show version命令前的准备 FReceivedData := ''; FExpectedPrompt := 'Router#'; // 根据实际设备提示符修改 FIsReceiving := True; // 命令后加回车换行,模拟终端输入行为 ScSSHShell.WriteString('show version' + #13#10);
3. 处理OnAsyncReceive事件
在事件中累积数据,并检查是否出现目标提示符:
procedure TForm1.ScSSHShellAsyncReceive(Sender: TObject; const Data: string); var PromptPos: Integer; begin if not FIsReceiving then Exit; // 累积接收到的所有数据 FReceivedData := FReceivedData + Data; // 检查是否出现目标提示符 PromptPos := Pos(FExpectedPrompt, FReceivedData); if PromptPos > 0 then begin FIsReceiving := False; // 数据接收完成,处理结果(截取提示符之前的有效输出) ShowMessage('命令执行完成,输出内容:' + Copy(FReceivedData, 1, PromptPos - 1)); // 重置变量,准备下一次命令执行 FReceivedData := ''; end; end;
4. 特殊场景处理
- 动态变化的提示符:比如进入配置模式后提示符变为
Router(config)#,需要在发送对应命令前更新FExpectedPrompt的值。 - 超时保护:为避免网络异常导致无限等待,可添加定时器处理超时:
// 定时器事件逻辑 procedure TForm1.Timer1Timer(Sender: TObject); begin if FIsReceiving then begin FIsReceiving := False; ShowMessage('命令执行超时'); FReceivedData := ''; Timer1.Enabled := False; end; end; // 发送命令时启动定时器(设置10秒超时示例) Timer1.Interval := 10000; Timer1.Enabled := True;
- 回显处理:部分设备会回显输入的命令,可在结果处理时判断并截取掉回显的命令行内容。
5. 关键配置注意
确保ScSSHShell的TerminalType设置为vt100,避免设备输出格式异常,影响提示符匹配。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

