摘要

  • RFC 1080 允许一个 Telnet 进程请求另一个进程开关软件流控,但前提是 DO 与 WILL 已先建立这项狭窄权限。
  • 选项控制的是用户侧 Telnet 进程到所接终端的本地输出路径,不是 TCP、远端应用或整个网络,也不证明本地驱动已经执行请求。
  • 协商成功会强制一个已知的“流控开启”初态;撤销选项后,控制权终止,本地状态可以回到实现自定的默认值。

两个字符,两个去处

RFC 854 的网络虚拟终端键盘能够生成全部 128 个 US-ASCII 码。对于远端编辑器来说,Control-S 与 Control-Q 完全可能是有意义的普通输入。

终端驱动却常把同样的值当作软件流控。XOFF 通常由 Control-S 触发,用来暂停屏幕输出;XON 通常由 Control-Q 触发,用来恢复。字符在本地就被消耗,远端程序根本看不到。

缓冲区快满或用户来不及阅读时,这种拦截有价值;编辑器正需要该按键时,它又会破坏输入。字节本身没有宣布最终含义。真正决定含义的是本地驱动状态,以及远端是否在这次会话中获得了请求改变状态的资格。

1988 年 11 月发布的 RFC 1080 把 TOGGLE-FLOW-CONTROL 定为 Telnet 选项 33。它标准化的不是终端所有权,而是一条范围很小的请求通道。

先同意谈,才能下达模式请求

RFC 855 把复杂 Telnet 选项分成两阶段:双方先用 DO/WILL 同意使用选项,之后才能在 SB … SE 中交换参数。

选项 33 的常见方向是远端主机发送 DO,连接物理终端的用户 Telnet 进程回复 WILL。前者表示愿意发送开关请求,后者表示愿意按请求调整自己的流控。

DONT 与 WONT 拒绝的是协议角色,而不是报告当前开关。一个客户端完全可以拒绝远端控制,同时仍按自己的默认策略启用 XON/XOFF。

完整的 DO/WILL 交换之前,不得发送 ON 或 OFF。选项被撤销之后同样不得继续。这个顺序把权限与命令分开:一条状态命令不能靠到达本身为自己创造合法性。

协议可以双向使用,但通常是不对称的。远端应用知道自己何时需要字面上的 Control-S;本地客户端拥有通往终端的实际字符路径。

协商本身建立了已知初态

双方同意后,DO 的发送者可以发出 ON 或 OFF。接收方调整的是用户 Telnet 进程到终端显示的流控处理,并没有缩小 TCP 接收窗口,也没有让服务器程序停止运行。

RFC 1080 规定:DO 与 WILL 一旦交换完成,WILL 的发送者必须立即开启流控。于是新建立的选项不会从未知状态开始;协商成功本身就给出了第一个状态。

但后续请求没有对应的状态确认。抓包可以证明一条合规的 OFF 已发出,却不能证明终端驱动支持并应用了它,更不能证明用户看见的输出确实暂停或恢复。

未知子命令应被忽略。这为以后扩展留下空间,也同时说明:沉默不是能力确认。

撤销权限,不等于冻结最后一次请求

任一方都可以用 DONT 或 WONT 终止选项。此后,只有重新完成 DO/WILL,才可再次发送模式请求。

本地状态并不保证停在最后一次 ON 或 OFF。规范允许它回到由实现定义的默认值。因此,只保存“最近看到的命令”会在撤销、重连或进程重启之后生成错误事实。

这条边界非常清楚:远端得到的是一段依附于协商状态的临时权限。权限结束时,本地策略重新生效。互操作并没有把远端偏好永久写进客户端。

这里的“流控”不是 TCP 流控

RFC 1080 只涉及用户 Telnet 进程向所接终端发送数据的方向。终端到客户端的输入可以有另一套处理;硬件流控还可能通过独立信号完成,不占用字符值。

它也不是拥塞控制。服务器可能继续产生输出,TCP 可能继续接收字节,缓存也可能继续保存数据。屏幕暂时不滚动,不等于网络停了。

所以每个判断都应写明方向和观测点。键盘上按下 Control-S、驱动吞掉 XOFF、网络里出现 OFF、屏幕实际暂停,是四条相连但不相同的证据。

Linemode 把其他本地解释另行归类

RFC 1184 后来定义 Telnet Linemode,让客户端在用户附近完成行编辑、回显和部分信号处理,再把完整行发往服务器。这在高时延链路上尤其有用。

流控在逻辑上与这些设置接近,但 RFC 1184 明确继续使用独立的 TOGGLE-FLOW-CONTROL,没有把它塞进新的模式位图。一个新选项不应悄悄重写另一个既有状态机。

调查时也应按链条拆开:键盘生成字符,驱动可能消费,Telnet 客户端可能转换,服务器应用最终可能接收。任何单点日志都不能代表整个过程。

RFC 1372 暴露了无法确认的兼容性

1992 年的 RFC 1372 取代 RFC 1080,保留 ON/OFF,又加入两种恢复规则。RESTART-XON 要求只由 XON 恢复输出;RESTART-ANY 允许除另一个 XOFF 外的任意字符恢复。

选项协商后,流控开启仍是已知事实;但“什么字符能够恢复”起初由系统自行决定。服务器需要另发请求,把恢复规则推向一个期望值。

协议却不能保证客户端具备两种能力。客户端可以因为系统限制而忽略请求,服务器没有收到这种拒绝的标准渠道。“应尽力遵守”不是确认报文。

很多驱动会吞掉 XON 与 XOFF;在任意字符恢复模式下,负责恢复的普通字符又可能继续上传给应用。一次按键可以同时改变本地输出状态并成为远端输入,具体结果仍需观察。

串口控制是另一套权力表面

RFC 2217 后来用 Telnet 控制串口,既能设置串口的输入输出流控,也定义 FLOWCONTROL-SUSPEND/RESUME,暂停客户端与接入服务器之间的数据和命令。

这些概念不能倒灌回 RFC 1080。设置 UART、暂停整段 Telnet 会话、决定本地驱动是否吞掉 XON/XOFF,分别控制不同对象,也需要不同证据。

IANA Telnet 选项登记表 至今把 33 记为 Remote Flow Control,并引用 RFC 1372。它证明编号含义仍受协调,不证明今天有多少客户端使用或正确实现。

把一个“模式”拆成五份记录

可靠的状态账本至少需要:

  1. 本次会话是否用 DO/WILL 建立权限;
  2. 权限有效时发送了哪个 ON、OFF 或恢复请求;
  3. 客户端和驱动实际应用了什么;
  4. 某个具体字符被消费还是被转发;
  5. 屏幕与应用最终观察到什么。

RFC 1080 直接给出前两层与一个协商初态,后面三层必须由本地或端到端观测补齐。

它留下的历史经验不是“远程控制终端”,而是如何把远程权限缩到一个可撤销、可拒绝、可定位的用途。只有选项仍有效、驱动仍按该状态解释时,Control-S 才是那条命令。

来源与证据边界

RFC 854 提供 NVT 字符背景,RFC 855 定义先同意再协商,RFC 1080 给出原始选项,RFC 1184 划出 Linemode,RFC 1372 扩展恢复规则,RFC 2217 区分串口与会话控制,IANA 保存登记。它们不证明当前部署、身份认证、一般授权、已应用的驱动状态、现实事故或用户结果。