作者[系统]
看板PttCurrent
标题[开发资讯] 连线保持与防闲置 (Keep-Alive) 实作建议
时间Wed Sep 23 23:29:53 CST 2026
PTT 终端机连线与防闲置 (Keep-Alive / Anti-Idle) 实作建议
为提升连线稳定度并避免干扰新版介面操作,我们建议所有实作「防闲置
(Anti-Idle)」或「连线保持 (Keep-Alive)」的 App / Web Client
开发者,一律改用标准 Telnet TIMING-MARK (RFC 860) 协定指令。
支援状态: PTT1 / PTT2 全站已原生支援 (无须等待伺服器改版)
适用於 WebSocket (wss://ws.ptt.cc/bbs) 连线
影响范围: 所有具备定时防闲置 (Anti-Idle / Keep-Alive) 或
断线侦测机制的 BBS Client / App / 浏览器扩充套件。
说明:
PTT 站方目前设定为「不会」因为使用者闲置而主动断线(除非系统负载过高)
所以理论上不需要特别设置防闲置功能,但由於现代网页与 App长期保持连线的
状况比较少见,许多网路设备(防火墙、路由器、...)都有长期无传输就切断
连线的机制,如果是行动网路甚至可能数分钟就切断。
因此,我们理解使用者会有防闲置的需求以配合实际网路。一般为了防止
使用者久未操作遭伺服器或网路设备断线,会定时在背景自动发送封包。
然而传统常见的几种做法存在明显副作用或网路层缺陷:
1. 传统防闲置做法的问题
(a) 定时发送一般按键或控制字元 (应全面停用)
- 常见旧做法:送出 NUL (0x00)、Ctrl-L (0x0C)、Space、Backspace、
Esc、或方向键组合 (如 \x1bOA\x1bOB) 等。
- 问题:这些位元组会进入 BBS 的键盘输入缓冲区 (vkey),被当作真
实按键处理。在各列表、单行输入提示 (getdata)、推文、编辑器或
新版 [i] 看板资讯等画面中,极易造成误触功能、关闭提示视窗、打
断输入状态或引发画面无故重绘,例如「画面会定期抖一下」。
(b) 定时发送 Telnet IAC NOP (0xFF 0xF1) 或 IAC AYT (0xFF 0xF6)
- IAC NOP (0xFF 0xF1) 属於「单向静默指令」:
伺服器收到後仅会在底层将其吸收忽略,【不会回传任何封包】。当
使用者处於行动网路、NAT 分享器、防火墙或 WebSocket Proxy 後方
时,由於缺乏「Server -> Client」的双向回应流量,中间网路设备
仍可能判定该连线已僵死 (Stalled / Half-open) 而切断连线,且
Client 端也无法藉此得知连线是否已经实质断开。
- IAC AYT (0xFF 0xF6, Are You There) 会污染画面:
伺服器收到 AYT 会直接回传明文字串 "I'm still alive.\r\n" 至画
面串流中,导致终端机画面出现杂讯与排版错乱。
2. 推荐标准做法:使用 Telnet IAC DO TIMING-MARK (RFC 860)
我们建议所有 Client 统一改送 Telnet TIMING-MARK (Option 6) 请求:
(a) 完全不干扰 BBS 状态与画面:
该序列在伺服器端输入管线的 Telnet 过滤层 (telnet_filter_process)
就会被完整拦截并消化,【不会进入vkey输入缓冲区】,不会对使用者
目前的画面、游标、选单或输入状态产生任何影响。
(b) 具备双向收发 (Ping / Pong) 效果:
伺服器收到 IAC DO TIMING-MARK 後,会立即在协定层主动回传 3 个
bytes 的协商回应。这能确保 Client 与 Server 双向皆有实际封包流
动,有效刷新中间路由器 / 防火墙 / WebSocket 的连线逾时计时器,
同时让 Client 可藉由是否收到回应来侦测半开断线 (Dead Peer)。
3. 实际传送与接收的位元组 (Bytes) 规格
(a) Client 发送端 (Request: 固定 3 Bytes):
触发防闲置时,请直接向底层 Socket / WebSocket 送出以下 3 个原始
位元组 (Raw Bytes):
* 协定语意:IAC + DO + TIMING-MARK
* 十六进位:0xFF 0xFD 0x06
* 十进位值:255, 253, 6
* 程式范例:new Uint8Array([0xff, 0xfd, 0x06]) (JavaScript)
b"\xff\xfd\x06" (Python / C)
* 各 Byte 定义:
- Byte 0: 0xFF (255): IAC (Interpret As Command)
- Byte 1: 0xFD (253): DO (请求对方执行选项)
- Byte 2: 0x06 ( 6): TIMING-MARK (RFC 860 Option 6)
【注意】发送此序列时,请走底层原始发送路径 (sendRaw),切勿经过
一般文字输入的 IAC 跳脱函式 (不可将 0xFF 变成 0xFF 0xFF)。
(b) Server 回应端 (Response: 固定 3 Bytes):
伺服器收到上述 3 Bytes 後,会立即回传以下 3 Bytes 协商回应:
* PTT (pttbbs) 回传:IAC + WONT + TIMING-MARK
- 十六进位:0xFF 0xFC 0x06 (十进位:255, 252, 6)
【注意】传回 WONT 而非 WILL 是故意的,因为 WILL 会要进入
下一步协商而不能再一直问,所以一般使用 TIMING-MARK
作的作法就是传 WONT 然後可以重复让 cilent 传 DO。
* 给第三方程式开发者的建议
1. 请将程式内的防闲置 (Anti-Idle) 发送内容改为上述的 3 Bytes 原始序列:
`0xFF 0xFD 0x06` (IAC DO TIMING-MARK),建议发送间隔设为 180~300 秒,
且当使用者有正常按键输入时即可重置计时器。
2. 请检查您的 Telnet 接收端状态机 (Inbound Filter):当收到伺服器回传的
`0xFF 0xFC 0x06` (IAC WONT 0x06) 或 `0xFF 0xFB 0x06` (IAC WILL 0x06)
时,请直接【忽略】,勿将其当作一般字元绘制到画面上。
3. 当收到伺服器的 `IAC WILL 0x06` (或 `WONT 0x06`) 回应时,Client 请勿
再自动回覆 `IAC DONT 0x06` (`0xFF 0xFE 0x06`),以免产生多余的往返封包。
4. 请全面移除送出 `0x00` (NUL)、`^L`、空白键或方向键等模拟按键的旧式防
闲置实作,以避免干扰使用者操作及画面状态判读。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/PttCurrent/M.1790178013.A.9FB.html