# WebSSH 终端输入回显延迟修复

**日期**: 2026-05-26
**变更摘要**: 修复 WebSSH 终端输入字符不即时显示的问题 — 将 async-for (readline) 改为 read() + 降低 bufsize

## 动机

1. 用户在终端输入字符后，字符不会即时显示（echo 延迟），必须按 Enter 后才一次性出现
2. 根因：`async for data in shell.stdout` 内部调用 `readline()` → `readuntil('\n')`，会缓冲所有数据直到遇到换行符
3. 交互式终端中，单字符 echo 永远不包含换行符，导致所有输入字符被缓冲直到用户按 Enter

## 变更内容

### server/api/webssh.py — 2处修改

**修改1: `_read_shell_output()` 函数 — 消除 readline 缓冲**
- 旧：`async for data in shell.stdout:` （内部 readline，等换行才 yield）
- 新：`while not shell.stdout.at_eof(): data = await shell.stdout.read(4096)` （有数据即返回）
- `read(n)` 使用 `exact=False`，只要缓冲区有数据就立即返回（最多 n 字节），不等换行

**修改2: `create_process()` 调用 — 降低 bufsize**
- 旧：`conn.create_process(term_type="xterm-256color", term_size=(24, 80))` （默认 bufsize=128KB）
- 新：`conn.create_process(term_type="xterm-256color", term_size=(24, 80), bufsize=4096)`
- 两处 create_process（主连接 + 失效重试连接）均添加 `bufsize=4096`
- 4KB 缓冲区足够单次交互 echo，同时大幅降低延迟

## 技术分析

asyncssh 数据流路径：
```
async for data in shell.stdout
  → SSHStreamProcess.__aiter__()
    → SSHStreamSession.aiter()
      → readline()
        → readuntil('\n')  ← 阻塞直到换行符
```

修复后路径：
```
while not shell.stdout.at_eof():
  data = await shell.stdout.read(4096)
    → SSHStreamSession.read(4096, exact=False)  ← 有数据即返回
```

## 涉及文件

- `server/api/webssh.py` — WebSSH WebSocket 处理（2处修改）

## 是否需迁移/重启

- 需重启后端（webssh.py 修改）
- 前端无改动

## 验证方式

1. 打开 terminal.html?server_id=8 → WebSocket 保持 OPEN，状态显示「已连接」
2. 输入 `whoami` → 字符即时显示（不等 Enter），按 Enter 后立即显示 `root`
3. 后端日志无 `shell creation failed` 错误
4. 终端交互流畅，无 echo 延迟
