RFC 5 带读:Decode Encode Language (DEL)——1969 年的可下载前端程序与跨终端交互

前言

读完 RFC 1~4,再打开 RFC 5,会突然发现画风变了。

前几篇还在讨论 Host Software、IMP、Link、网络联调和 RFC 文档制度,RFC 5 却直接拿出了一门编程语言:

DEL(Decode-Encode Language,解码-编码语言)

而且这不是一份只有几页的概念提案。RFC 5 从网络交互模型一路写到语言语法,里面有:

  • Function、Procedure、Co-routine;
  • Integer、Real、Tree、Pointer、Buffer;
  • IFWHILEFORCASEGO TO
  • Message 的构建、发送和接收;
  • Display Buffer;
  • Vector、Beam Position、Intensity、Blink、Italics;
  • Wand、Joystick、Keyboard、Buttons、Light Pen,甚至 Mouse

如果只把它当作“一门没流行起来的古老语言”,就会错过 RFC 5 真正有意思的部分。

DEL 想解决的核心问题其实是:

当用户通过一个慢速网络,使用本地完全不同的计算机和终端,去操作远端交互式系统时,怎样避免每一次按键、显示变化和设备差异都必须由远端主机处理?

它给出的答案非常大胆:

1
2
3
4
5
6
7
8
9
10
11
远端应用

│ 下发一段符号形式的 DEL 程序

用户所在 Host

├── 本地编译
├── 本地处理按键、回显和部分显示逻辑
├── 本地适配实际终端硬件

└── 只有真正需要远端处理的信息才走网络

也就是说,RFC 5 试图把一部分远程应用的前端逻辑下沉到用户所在的计算机执行

这不是 JavaScript,也不是 Java Applet,更不是现代 Edge Computing 的直接祖先,但其思想与今天很多系统非常容易产生共鸣:

1
2
3
4
5
6
7
Code on Demand
Smart Client
Local Fast Path
Server-driven UI
Remote UI
Edge-side Processing
Portable Intermediate Representation

这种相似并不是后人硬凑出来的。

Steve Crocker 在 1999 年的 RFC 2555《30 Years of RFCs》 中回顾这段历史时,明确提到他们当时想在会话开始时下载一个小程序,由它控制交互并更有效地使用窄带网络;他把 DEL 看作这一思路的早期尝试,并在回顾中把 Java、ActiveX 与这种早期设想联系起来。

2019 年的 RFC 8700《Fifty Years of RFCs》 又进一步概括:早期 Network Working Group 曾设想 application-specific protocols(应用特定协议),并把代码下载到用户站点,DEL 是最初版本,后来又发展出 NIL(Network Interchange Language)。

所以 RFC 5 最值得带读的,不是每一个古老语法符号。

真正值得理解的是:

1969 年,网络还没正式投入使用时,人们已经在思考“远端应用、可下载代码、本地运行时、统一设备抽象、本地即时反馈和语义化显示”应该怎样组合起来。

RFC 基本信息

项目 内容
RFC RFC 5
官方英文标题 Decode Encode Language (DEL)
作者 Jeff Rulifson(J. Rulifson)
所属机构 SRI(Stanford Research Institute)
工作组 Network Working Group
文档日期 June 2, 1969
RFC Editor 当前发布日期 June 1969
RFC Editor 当前状态 Unknown
Stream Legacy
早期 NIC 文档号 4691
RFC Editor 信息页 RFC 5: Decode Encode Language (DEL)
RFC 原文 RFC 5 原文

RFC 5 原文页眉中的年份曾显示为:

1
June 2, l969

这里的 l 是 OCR 把数字 1 识别成了字母 l。RFC Editor 已有 Verified Editorial Erratum 将其确认应为:

1
June 2, 1969

RFC 5 是“工作文档”,不是定稿语言标准

RFC 5 在摘要之后直接声明:

这是用于 DEL 语言演化的 working document。

所以阅读时必须注意:

1
2
3
RFC 5

最终稳定的 DEL Language Specification

原文中到处保留着这种“设计还在现场发生”的痕迹,例如:

1
It is not clear just how global declarations are to be??

以及:

1
2
Strings are a big problem?
Rulifson also wants to get rid of real numbers!!

甚至在讨论 program composition 时直接留下一句:

1
when Crocker tells us how??

这不是后人整理好的标准,而是一份真实的设计工作稿。

RFC 5 没有被 RFC Editor 标成“Obsoleted by RFC X”

这一点与 RFC 3、RFC 4 不同。

RFC Editor 当前没有给 RFC 5 标出一个直接的:

1
Obsoleted by RFC ...

而 1971 年的 RFC 100《Categorization and Guide to NWG/RFCs》 甚至把 RFC 5 放入:

1
D.4 NIL, DEL, Form Machines

并用 * 标记在当时的 current issues 子集中。

因此不能简单写成:

1
RFC 5 很快被某篇 RFC 正式废弃。

更准确的历史关系是:

1
2
3
4
5
6
7
8
9
DEL / RFC 5

├── 继续参与“数据和交互如何适配网络”的研究

└── 思路进一步演化

NIL / RFC 51

Form Machine 等其他方案

后来 ARPANET 实际协议体系并没有把 DEL 作为通用网络执行环境部署下来,但它属于一条持续了一段时间的研究路线。

为什么会有这篇 RFC

一、最初的 ARPANET 首先面对的是“远程交互”

RFC 5 的 Foreword 记录了一个很重要的时间点:

1
2
October 25-26, 1968
SRI

最初的 ARPA Network Working Group 在 SRI 开会。

参会者包括:

  • Andrews;
  • Baray;
  • Carr;
  • Crocker;
  • Rulifson;
  • Stoughton。

文档说,在开会之前,大家大体已经认同:

通过网络运行 interactive programs(交互式程序),会是最先遇到的问题之一。

这和今天想象“计算机联网”时很不一样。

今天我们第一反应可能是:

1
2
3
4
HTTP API
文件下载
消息队列
数据库连接

但 1968~1969 年的核心场景之一是:

1
2
3
4
5
人在本地终端前

通过网络

操作远方的大型分时计算机

换句话说,他们很早就在面对:

Remote Interactive Computing(远程交互式计算)

二、50 Kbit/s 在当时已经让他们担心交互体验

Steve Crocker 在 RFC 2555 回忆,当时 ARPANET 使用的通信线路大约是:

1
50 kilobit per second

他们担心这个带宽不足以提供高质量的交互式体验。

但 DEL 面对的问题不仅是纯吞吐量。

真正棘手的是:

1
2
3
4
5
6
7
8
9
10
11
12
13
用户按一下键

跨网络发给远端

远端分时系统被唤醒

处理按键

生成反馈

再跨网络返回

本地终端显示

如果每一个字符、按钮、光笔动作、鼠标动作都必须如此处理,那么:

  • 网络 RTT 会进入用户交互关键路径;
  • 远端 TSS 会频繁被激活;
  • 本地 TSS 也可能承担额外负载;
  • 不同终端的特殊能力很难利用;
  • 显示系统需要传输大量低层绘图数据。

RFC 5 明确指出,对于大型 display-oriented systems,如果每次按钮状态变化都必须激活 TSS 中的用户程序,通过网络运行时甚至会同时给两个系统造成不必要负担。

三、问题不仅是“慢”,还有终端完全不一样

早期网络并不是:

1
2
3
浏览器 A
浏览器 B
浏览器 C

大家都实现一个近似统一的 Web Platform。

而是不同站点有完全不同的:

1
2
3
4
5
6
7
8
9
10
11
Host
Operating System
Character Set
Display Hardware
Keyboard
Buttons
Light Pen
Mouse
Joystick
Storage Tube
High-speed Display

因此如果 Utah 的终端要访问 SRI 的 NLS,问题不是简单地:

1
send(keyCode)

因为:

1
2
3
Utah 的 keyCode
不一定等于
SRI 940 的 keyCode

更麻烦的是显示。

假设服务端想表达:

1
画一条横跨屏幕的直线

不同终端的:

  • 分辨率;
  • 坐标系统;
  • 向量能力;
  • 存储管能力;
  • 字符宽度;
  • 强度;
  • 闪烁;

可能完全不同。

如果服务端直接输出某台设备的硬件命令,就无法跨站点工作。

四、直接为每一对机器写转换器,会迅速失控

假设网络中有 N 种不同的交互环境。

最笨的方式是:

1
2
3
4
5
A → B 写一个 translator
A → C 再写一个
A → D 再写一个
B → A 再写一个
...

概念上会趋向:

1
O(N²)

种两两适配关系。

RFC 5 的目标之一就是减少这种 pairwise translation(两两转换)。

它提出一个中间的:

Universal Hardware Representation(通用硬件表示)

思路变成:

1
2
3
4
5
Local Hardware

Universal Representation

Remote Application Representation

这样每个站点主要负责:

1
本地硬件 ↔ 通用表示

每个服务系统负责:

1
通用表示 ↔ 自己的逻辑语义

从架构上看,这比 N×N 的硬编码转换更容易扩展。

这里的 O(N²)O(N) 是站在今天对其设计动机做的抽象,不是 RFC 5 原文给出的复杂度公式;原文明确说的目标是:

minimize the number of translators needed

五、为什么不是传一个固定协议,而是“传程序”

如果所有应用都只需要 TTY,那么可以设计一套固定字符协议。

但 RFC 5 设想的范围更大:

1
2
3
4
5
6
7
简单字符终端

有 Echo Table 的 TTY

复杂图形终端

NLS 等大型交互系统

复杂交互系统的即时反馈规则可能完全不同。

所以它没有试图把所有应用行为都写死在一个巨大通用协议里,而是提出:

由服务端把针对该 subsystem 的 DEL 程序以 symbolic form(符号形式)发送到用户站点,再由用户站点本地编译。

这就是 RFC 5 最核心的思想。

核心内容

RFC 5 可以从五层理解:

1
2
3
4
5
1. DEL 的应用目标
2. NST:运行 DEL 的公共支撑库
3. Universal Hardware Representation:跨设备抽象
4. Encode / Decode:双向数据和显示转换
5. DEL Language:真正描述这些转换行为的语言

整体架构可以先画成:

flowchart LR
    UI[本地交互设备<br/>Keyboard / Mouse / Light Pen / Display]
    UHR[Universal Hardware Representation]
    ENC[DEL Encode Program<br/>本地编译]
    NSTU[NST Runtime / Library<br/>User Host]
    NET[ARPANET / IMP Network]
    DECODE[DEL Decode Program]
    NSTS[NST / Host-side Support]
    APP[Server-host Subsystem<br/>例如 NLS]

    UI --> UHR
    UHR --> ENC
    ENC --> NSTU
    NSTU --> NET
    NET --> NSTS
    NSTS --> APP

    APP --> DECODE
    DECODE --> NET
    NET --> NSTU
    NSTU --> UHR
    UHR --> UI

这张图是根据 RFC 5 的文字结构重构的,不是原文正式架构图。

一、DEL 的两个基本任务

RFC 5 摘要把 DEL 的任务定义得非常清楚。

任务 1:用户 → 网络

接受 interactive console 的输入码:

1
Console Input

然后:

1
2
3
4
5
立即给用户反馈
+
把结果打包进网络 Message
+
发送到远端

任务 2:网络 → 用户

从另一台计算机接收 Message:

1
Network Message

然后:

1
2
3
4
5
解包
+
建立 display information tree
+
把结果送到用户交互站

这两项任务直接对应:

1
2
Encode
Decode

所以语言叫:

1
Decode-Encode Language

二、NST:Network Standard Translator

RFC 5 把 **NST(Network Standard Translator)**描述为一组公共程序库。

它的职责是:

与用户站点从 DEL 程序编译出来的代码有效配合。

可以把它理解成一种:

1
Standard Runtime / Translation Library

但不要直接把它等同于 JVM、浏览器 Runtime 或现代 VM。

RFC 5 的设计更像:

1
2
3
4
5
每个节点实现一次 NST Library
+
服务端按 subsystem 下发 DEL symbolic program
+
用户节点把 DEL 编译成本机代码

三、NST-DEL 支持三个复杂度层次

RFC 5 特意强调,这套模型不是只为复杂图形系统服务,而是可以从简单模式逐级升级。

Level 1:几乎不转换

最低层模式中,信息直接以用户程序平时在 user-host 中接收的形式发送给 server-host。

这时 NST 基本:

1
defaults to inaction

DEL 程序主要只是:

1
2
3
Message Builder
+
Sender

也就是说,如果两边足够兼容,就不要为了“统一架构”强行增加转换。

Level 2:TTY + Echo Table

中间层用于普通 TTY。

DEL 程序在 user-host 上:

1
2
3
4
5
6
7
8
9
接收键盘字符

本地 Echo

转换成 server-host Character Set

打包 Message

遇到适当 Break Character 时发送

服务端返回时:

1
2
3
4
5
6
7
Server-host Character Set

DEL Translation

User-host Character Set

本地 TTY 输出

流程可以画成:

sequenceDiagram
    participant U as User TTY
    participant D as Local DEL/NST
    participant N as Network
    participant S as Server Host

    U->>D: 输入字符
    D-->>U: Immediate Echo
    D->>D: Character Translation / Buffer
    Note over D: Break 条件满足时
    D->>N: Packed Message
    N->>S: Server-format Input
    S-->>N: Response
    N-->>D: Server-format Output
    D->>D: Translate to Local Character Set
    D-->>U: Print / Display

Level 3:大型图形交互系统

最激进的模式用于复杂 display-oriented systems。

这时本地 DEL 程序不只是做字符回显,而会处理:

1
2
3
4
5
6
按钮
光笔
鼠标
图形反馈
命令状态
显示管理

大量“立即反馈”在本地完成。

只有达到某些重要交互点时,才向 server-host 发 Message。

架构变成:

1
2
3
4
5
6
7
8
9
10
11
User Action

├── trivial / immediate feedback
│ ↓
│ local

└── requires server computation

network

server-host

这就是 DEL 最核心的性能思想:

把高频、低价值、延迟敏感的交互留在本地;把真正需要远端计算的部分交给服务端。

四、Universal Hardware Representation:给不同设备找一个公共语言

RFC 5 为了减少设备之间的转换器数量,提出:

Universal Hardware Representation(UHR,通用硬件表示)

它不是一套真实统一硬件,而是:

一种用于统一描述初始网络中各种交互式显示站硬件的抽象表示。

最直观的例子是屏幕坐标。

RFC 5 不要求统一真实像素分辨率,而是假定屏幕是一个正方形:

1
2
3
中心 = (0, 0)
X 范围 = -1 ~ +1
Y 范围 = -1 ~ +1

可以表示为:

1
2
3
4
5
6
7
8
(-1,+1)              (+1,+1)
+-------------------+
| |
| (0,0) |
| • |
| |
+-------------------+
(-1,-1) (+1,-1)

于是一个点不再依赖:

1
2
3
4
1024 × 1024
512 × 512
某种向量显示器
某种存储管

而是用归一化坐标描述。

这其实是一种非常经典的抽象思路:

1
2
3
4
5
Physical Device

Logical Device Model

Application Semantics

五、Logical Screen 比“像素流”更重要

在 DEL 的显示语义里,RFC 5 不只定义坐标。

它还提出:

1
PREG = <x, y, r>

其中:

  • xy 表示位置;
  • r 表示相对 x 轴逆时针旋转的弧度。

Intensity 则归一化到:

1
2
0 → black
1 → display 能达到的最亮

另外还有:

  • character frame size;
  • blink bit;
  • italics;
  • vector;
  • beam position。

RFC 5 最值得注意的一句话是:

如果要画一条横跨屏幕的直线,就应该传输“这是一条直线”这个事实,而不是传 500 个短向量。

这说明作者希望网络上传输的是:

1
更高层的逻辑实体

而不是:

1
低层设备指令序列

抽象一下就是:

1
2
3
“Draw Line A→B”

本地设备决定怎样真正画出来

而不是:

1
2
3
4
5
Move beam 1
Move beam 2
Move beam 3
...
Move beam 500

这种思想与现代:

  • Vector Graphics;
  • Scene Graph;
  • Declarative UI;
  • Remote Rendering Protocol;

在抽象层上很相似。

但不能写成“SVG 或 React 直接源自 RFC 5”。RFC 5 只是在面对同一个基本问题:

网络上到底应该传设备细节,还是传更稳定的语义?

六、输入设备抽象非常超前

RFC 5 的 LOGICAL INPUT DEVICES 直接列出:

1
2
3
4
5
6
Wand
Joy Stick
Keyboard
Buttons
Light Pens
Mice

注意这里有:

Mice

这不是说 RFC 5 定义了现代鼠标网络协议。

它说明 DEL 从一开始就不是只为:

1
ASCII Keyboard + Printer

设计的。

它试图覆盖一种更一般的:

1
Human ↔ Interactive Computer System

交互模型。

关键机制与工作流程

一、核心机制:服务端把“适配程序”发给用户端

RFC 5 用 NLS 举了一个非常具体的例子。

假设 Utah 的用户想使用 SRI 的 NLS。

流程是:

sequenceDiagram
    participant U as Utah User
    participant UH as Utah User-Host
    participant S as SRI NLS / Server Host

    U->>UH: 请求进入 NLS
    UH->>S: 请求 NLS 所需 symbolic program
    S-->>UH: DEL Remote Encode Program (REP)
    UH->>UH: Compile REP for local machine
    UH->>UH: Load with NST standard library
    U->>UH: Keyboard / Mouse / Console Input
    UH->>UH: Local Translation + Immediate Feedback
    UH->>S: 只发送需要远端处理的 Message
    S-->>UH: Logical / Display Response
    UH-->>U: 转换为本地设备输出

RFC 5 把这个 DEL 程序称为:

NLS Remote Encode Program(REP)

REP:

1
2
3
4
5
6
7
接受 Universal Hardware Representation 输入

转换为 NLS 能使用的格式

可进行 Buffering

可进行 Local Feedback

当程序第一次到达 Utah:

1
2
3
4
5
6
7
symbolic form

compile

load with standard library

run locally

这个细节非常重要:

RFC 5 不是要求服务端为每一种远端机器预编译一份二进制程序,而是传输符号程序,让接收站点根据自己的机器进行编译。

二、为什么传 Symbolic Program,而不是 Machine Code

RFC 5 明确列出这种方式的优势。

每个站点可以:

1
用自己认为最合适的方式编译

因此本地编译器可以针对:

  • 本机字长;
  • 指令集;
  • 终端硬件;
  • 特殊按钮;
  • 本地 Monitor;

生成更合适的 Machine Code。

原文期待得到:

1
2
3
faster run times
+
greater code density

也就是说:

1
2
3
4
5
Portable Source

Site-specific Compilation

Native Efficient Code

这是一种非常有意思的 portability 策略。

三、服务端升级后,远端前端也可以随之更新

RFC 5 还强调:

如果 host-site 的系统增加新功能,host programmer 只需要更新:

1
symbolic encode program

用户站点下次收到并编译新程序以后,新功能就会随之进入远程访问环境。

即:

1
2
3
4
5
6
7
8
9
Server Feature Change

New DEL Program

Remote Download

Local Compile

Remote User Gains New Capability

这已经有非常明显的:

1
server-driven client behavior

味道。

它解决的不是单纯“数据格式升级”,而是:

应用交互逻辑如何与服务端版本一起演进。

四、本地站点仍然可以插入自己的扩展

RFC 5 并不希望远端下发的程序完全控制本地终端。

原文说,user-site programmer 可以在本地 Monitor System 和 host 下发的 DEL program 之间插入额外 symbolic programs。

用途包括适配:

1
2
3
unusual keys
buttons
特殊显示硬件

所以整体不是:

1
Server controls everything

而更像:

1
2
3
4
5
Server-provided Logic
+
User-site Adapter
+
Local Hardware Runtime

这也是 DEL 试图解决“非标准终端模拟另一种非标准终端”的方法。

五、User-to-Host 数据流

RFC 5 对用户到服务端的数据路径写得很细。

可以重构成:

flowchart LR
    DEV[Keyboard / Buttons / Mouse<br/>Local Devices]
    MON[Monitor / Interrupt Handlers]
    ENC[Encode Translator<br/>DEL]
    FB[Local Display Management<br/>Immediate Feedback]
    MSG[Message Packing]
    IMP1[User-site IMP]
    NET[ARPANET]
    IMP2[Server-site IMP]
    HRT[Host Reception Program]
    APP[Server Subsystem]

    DEV --> MON --> ENC
    ENC --> FB
    ENC --> MSG --> IMP1 --> NET --> IMP2 --> HRT --> APP

Encode Translator 可以做:

1
2
3
4
5
6
多字符 → 单字符
单字符 → 多字符
Character Translation
按 Break Character Buffer
Immediate Feedback
Message Packing

所以它不是一个简单的 charset.convert()

它是:

输入流状态机 + 本地反馈逻辑 + 协议编码器。

六、Host-to-User 数据流

反方向更复杂。

服务端输出首先进入:

1
Decode

它将输出转换成简化的:

1
Logical Entity Output Stream

然后经过网络,在用户端继续由:

1
2
3
User Reception Translator
Display Control
Program Control

处理。

可以画成:

flowchart LR
    APP[Server Subsystem]
    DEC[Decode Translator]
    LOGIC[Logical Entity Stream]
    NET[ARPANET / IMP]
    URT[User Reception Translator]
    DCTRL[Display Control]
    PCTRL[Program Control]
    DISPLAY[Local Display]
    SUBSYS[Local Subsystem / Storage]

    APP --> DEC --> LOGIC --> NET --> URT
    URT --> DCTRL --> DISPLAY
    URT --> PCTRL --> SUBSYS

其中 Program Control 还可以把数据选择性地路由到本地其他 subsystem。

RFC 5 举例说:

1
2
3
4
5
6
7
Floating-point block

转换为 user-style words

作为 block

送本地 subsystem 处理或存储

这说明 DEL 想处理的并不只是字符和图像,还有:

1
structured / binary data

七、本地显示为什么要保留“逻辑结构”

RFC 5 认为服务端输出应该尽量携带逻辑意义。

例如不同用户终端的行宽可能不同,所以不应该只发“已经排好版的物理字符位置”,而应该保留:

1
logical line identity

同理:

1
一条直线

应该作为一个逻辑实体传输,而不是拆成大量微小向量。

原因是:

1
2
3
4
5
Semantic Representation

User-site Rendering

适配不同硬件

这样实时显示操作的责任就可以:

1
shift closer to the user

也就是向用户端下沉。

八、Co-routine:用于组织流式交互转换

RFC 5 Foreword 记录:

1
2
November 18, 1968
Crocker + Rulifson

的一次讨论导致 DEL 加入了正式的:

Co-routines(协程)

RFC 5 的语法里,Function、Procedure 和 Co-routine 被明确区分。

其中:

1
2
3
Function  → 返回值
Procedure → 不返回值
Co-routine → 通过 Pipe 组织执行入口与数据交换

语言还定义:

1
2
STUFF exp IN pipename
FETCH pipename

可以把这种机制抽象理解为:

flowchart LR
    A[Coroutine A]
    P[PIPE]
    B[Coroutine B]

    A -->|STUFF value IN pipe| P
    P -->|FETCH pipe| B

它非常适合描述:

1
2
3
4
5
6
7
8
9
输入

转换

缓冲

反馈

网络输出

这种多阶段数据流。

不要把 RFC 5 的 Co-routine 直接等同于今天 Java/Kotlin/Go/async runtime 的协程实现;这里重要的是:

语言设计者已经需要一种比普通 Call/Return 更适合流式交互处理的控制结构。

九、DEL 的语言结构其实相当完整

虽然 RFC 5 是 Working Document,但其 Language 部分已经覆盖大量传统语言结构。

Procedure Model

支持:

1
2
3
FUNCTION
PROCEDURE
CO-ROUTINE

Data / Declaration

可见的类型与结构包括:

1
2
3
4
5
6
7
8
INTEGER
REAL
CONSTANT
TREE
POINTER
BUFFER
LABEL
PIPE

Arithmetic

支持:

1
2
3
4
5
6
+
-
*
/
mod
bit operations

Logic

支持:

1
2
3
4
5
6
7
8
AND
OR
NOT
<
>
<=
>=
=

而且原文明确希望编译器对:

1
2
false AND ...
true OR ...

跳过不必要的后半部分计算。

也就是今天熟悉的:

Short-Circuit Evaluation(短路求值)

Flow Control

支持:

1
2
3
4
5
6
7
8
9
IF ... THEN ... ELSE
WHILE
UNTIL
FOR
CASE
ITHCASE
GO TO
CALL
RETURN

十、Semi-Tree:显示数据并不是平铺 Buffer

DEL 还定义了:

1
2
TREE
POINTER

以及:

1
2
3
4
5
6
7
8
9
10
up
down
forward
backward
head
tail
left brother
right brother
first daughter
last daughter

用于构建和操作 Semi-Tree

原文还明确说,额外括号可以像 LISP 一样产生线性子分类。

这说明 DEL 对复杂显示的设想不是简单:

1
byte[] frameBuffer

而更接近:

1
2
3
4
5
结构化显示对象

Tree

Local Rendering

十一、Message I/O 是语言一级能力

DEL 直接把网络 Message 构建写进语言语法。

原文包含类似:

1
2
3
4
5
6
7
8
start message
append message byte ...
send message

demand message
get message byte
message length
message empty

也就是说,DEL 不是一门与网络无关的通用语言再调用外部 Socket Library。

它是一门:

为网络交互与表示转换专门设计的 Domain-Specific / Special-purpose Language。

当然,当时还没有今天意义上的 Socket API。

十二、Display Buffer 同样是语言一级对象

DEL 提供:

1
2
3
start buffer
append ...
establish buffer

Buffer 中可以追加:

1
2
3
4
5
6
parameters
character
string
vector
beam position
curve

显示参数包括:

1
2
3
4
intensity
character width
blink
italics

这让 DEL 同时具有:

1
2
3
4
5
Network Message DSL
+
Display DSL
+
Control-flow Language

的特征。

重点概念与术语

DEL

DEL(Decode-Encode Language)

一种面向网络交互、终端适配和显示转换的 machine-independent language 设想。

其核心用途不是普通业务计算,而是:

1
2
Encode Local Interaction → Network / Server Form
Decode Server Output → Local Logical / Display Form

NST

NST(Network Standard Translator)

RFC 5 所设想的公共 Translator Library / Runtime。

每个节点实现 NST,再运行从 DEL symbolic program 编译出来的本地代码。

Universal Hardware Representation

Universal Hardware Representation(UHR)

用于抽象不同站点交互硬件的公共逻辑表示。

典型例子:

1
2
3
4
Logical Screen:
X = -1..+1
Y = -1..+1
Center = (0,0)

User-host

用户实际所在的 Host。

负责接收本地输入设备事件、运行本地 DEL/NST 逻辑、显示反馈并访问远端服务。

Server-host / Serving-host

运行被访问 subsystem 的远端 Host。

例如 RFC 5 示例中的 SRI NLS 所在系统。

NLS

NLS(oN-Line System)

Douglas Engelbart 团队在 SRI 开发的交互式系统,也是最早期 ARPANET 远程交互实验的重要对象。

RFC 1 和 RFC 5 都反复使用它作为复杂网络交互案例。

REP

REP(Remote Encode Program)

RFC 5 示例中的:

1
NLS Remote Encode Program

由 NLS 提供,使用 DEL 描述,下载到远端用户 Host 并在那里编译运行。

原文稍后有一处写成 NLS NEP,文本本身存在这种不一致;阅读时不宜擅自把所有缩写静默“修正”为同一个名称。

Encode Translator

处理:

1
2
Local Input
→ Server-suitable Input Stream

同时可以承担:

  • 字符转换;
  • 字符聚合;
  • Break 判断;
  • Message Packing;
  • Immediate Feedback。

Decode Translator

把 server-host 的输出转换为更通用、逻辑化的输出结构。

例如把:

1
500 short vectors

提升为:

1
one logical straight line

Immediate Feedback

即时反馈

用户输入后无需等待远端 Host 往返即可生成的本地反馈。

这是 DEL 降低交互延迟和 TSS 负载的核心机制。

Break Character

用于决定什么时候应该把已经 Buffer 的字符真正发送到 server-host 的控制字符或条件。

DEL 在普通 TTY 模式中可以持续本地处理,直到遇到适当的 Break Character 才形成 Message。

TSS

TSS(Time-Sharing System,分时系统)

RFC 5 担心复杂交互会因为每个按钮或输入事件反复激活用户程序,给本地和远端 TSS 都增加额外负担。

Symbolic Program

以符号形式传输的 DEL 程序,而不是某一种机器的原生 Machine Code。

接收端负责:

1
compile → local native code

Co-routine

DEL 的控制结构之一。

配合 PIPESTUFFFETCH 描述交互数据流和可恢复执行过程。

Semi-Tree

DEL 用来组织结构化显示信息的数据结构。

具有:

1
2
3
4
pointer
brother
daughter
up/down/forward/backward

等操作。

PREG

逻辑屏幕的位置寄存器:

1
PREG = <x, y, r>

r 为逆时针旋转角,单位为 radians。

NIL

NIL(Network Interchange Language)

DEL 后续的一条演化路线。

RFC 51 提出 NIL,引入更一般化的 Network Machine 抽象。

RFC 8700 直接把:

1
DEL → NIL

描述为这条早期网络语言思想的前后版本。

需要特别注意的点

1. DEL 不是“1969 年的 JavaScript”

这类类比很吸引人,但容易写过头。

DEL 与现代浏览器脚本确实有相似点:

1
2
3
4
5
6
7
远端提供程序

用户端运行

本地处理交互

与远端系统通信

Steve Crocker 后来也明确把这类早期想法与 Java、ActiveX 联系起来。

但技术谱系上不能写成:

1
DEL → JavaScript

RFC 5 没有:

  • DOM;
  • Browser;
  • HTTP;
  • JavaScript Runtime;
  • Web Security Model;
  • Same-Origin Policy。

正确说法应该是:

DEL 是非常早期的 downloadable interaction code / mobile-code-like 架构尝试,后来出现的 Java、ActiveX 等让 Crocker 看到了相似思想的再次出现。

2. DEL 也不是现代 Thin Client 的简单翻版

普通 Thin Client 常把大量逻辑集中到 Server。

DEL 反而强调:

1
2
把 Immediate Feedback
尽量移到 User Host

所以它同时具有:

1
2
3
Remote Service
+
Local Smart Front End

两个方向。

3. “Machine Independent”并不意味着语义真的完全可移植

RFC 5 自称 DEL 是:

1
machine independent language

但在 Arithmetic 部分又明确写:

1
2
all arithmetic and bit operations
发生在运行机器自己的 mode and style 中

作者甚至警告:

如果程序依赖 word length、two’s complement arithmetic 等机器细节,最终会遇到问题。

这是一个非常有意思的矛盾:

1
2
3
Source Language Portable

Program Semantics Automatically Portable

今天依然如此。

例如:

  • integer overflow;
  • endianness;
  • floating point;
  • undefined behavior;
  • native ABI;

都可能让“跨平台源码”在不同机器上产生不同结果。

4. UHR 是抽象设备,不是网络硬件标准

Universal Hardware Representation 很容易被误解成:

1
大家必须购买同一种终端硬件

实际上恰好相反。

它的目的就是:

1
2
允许真实硬件保持不同
但对上层暴露公共逻辑模型

5. -1..+1 坐标不是现代 NDC 的直接来源

今天图形学中也存在 normalized device coordinates。

RFC 5 的归一化屏幕与现代 NDC 在思想上非常相似,但没有证据表明今天的图形 API 是从 RFC 5 直接继承这套坐标系统。

应把它理解为:

面对跨显示硬件适配问题时,自然产生的一种归一化抽象。

6. 原文中很多 Syntax 本身就不稳定

RFC 5 有大量:

  • 拼写错误;
  • OCR 问题;
  • 不完整语法;
  • ??
  • 未完成 Sample Program;
  • 空的 AUDIO OUTPUT DEVICES 小节。

因此不应该拿 RFC 5 当前机器可读文本直接实现一个“严格兼容 DEL Compiler”,然后声称这就是唯一正确语法。

它是 Working Document。

7. byte 在 RFC 5 中也不能默认等于今天的 8 bit octet

RFC 5 的语法甚至允许声明:

1
message bytes are ... bits long

早期计算机里的 byte 并没有今天“固定等于 8 bit”的普遍语义。

所以阅读老 RFC 时看到:

1
2
3
byte
word
character

都需要结合时代语境。

8. Source 中的 byutemessage1 等文本不要强行现代化

当前文本中存在类似:

1
2
append message byute
message1 length

这样的字符串。

这些可能来自原稿、转录或 OCR。

写带读博客时应该解释语义,而不是假装当前文本是一份现代 EBNF,可直接复制粘贴生成 Parser。

9. DEL 的安全模型几乎为空

这是站在今天看最严重的局限之一。

RFC 5 的核心操作是:

1
2
3
4
5
6
7
8
9
Remote Server

发送 Symbolic Program

Local Host

Compile

Execute

但文档基本没有讨论:

1
2
3
4
5
6
7
8
9
10
11
Server Authentication
Code Signing
Sandbox
Capability
Permission
Resource Limit
Memory Isolation
File-system Access
Network Access
Malicious Code
Supply-chain Attack

1969 年的研究网络环境与今天公开互联网的威胁模型完全不同。

如果今天重新设计这种系统,安全模型绝不能缺席。

10. Symbolic Download 的版本同步很漂亮,但也引入供应链问题

RFC 5 认为远端系统更新 DEL symbolic program 后,用户站点自动获得新功能是一个优势。

站在今天看,这同时意味着:

1
2
Server 可以改变
客户端随后执行的代码

现代系统必须进一步回答:

1
2
3
4
5
6
谁发布?
发布了什么?
是否签名?
能否回滚?
是否可审计?
版本是否兼容?

11. RFC 5 不是后来 ARPANET 的通用应用协议

DEL 的想法没有成为所有 Host 必须实现的统一交互层。

RFC 8700 回顾说,在 BBN 给出 Host-IMP 硬件和软件接口规范后,Network Working Group 的注意力转向更底层的协议问题,早期“自动下载代码”的雄心一度消退。

因此不要把 DEL 放进这样一条错误栈:

1
2
3
4
5
6
7
IMP

NCP

DEL

All Applications

历史没有这样定型。

12. RFC 5 后续更准确的演化方向是 NIL 等 Network Language 研究

1971 年的 RFC 100 把:

1
2
3
4
5
6
RFC 5  DEL
RFC 31 Message Description Language
RFC 42 Message Data Types
RFC 51 NIL
RFC 80 / 83 Form Machine
RFC 96 NLS Front End

放在同一类问题下讨论。

这个问题是:

怎样让 user programs、data 和 network 之间进行可描述、可转换的适配。

所以 RFC 5 的影响不应该只从“编程语言史”看,还要从:

1
2
3
4
Data Representation
Protocol Translation
Remote Interaction
Network Language

这些方向看。

13. “直线而不是 500 个 Vector”是语义压缩,不只是带宽压缩

如果只是为了省带宽,可以简单压缩二进制。

RFC 5 更进一步:

1
保留对象的逻辑含义

因为本地拥有语义以后,可以:

  • 根据自己的显示器重新渲染;
  • 适应不同分辨率;
  • 进行本地操作;
  • 避免绑定远端硬件表示。

这比单纯 gzip 一串设备命令更高级。

14. Immediate Feedback 不是最终业务结果

本地 DEL 可以立刻回显字符、更新显示、处理某些控制动作。

但这不代表 server-host 已经接受或执行相应业务操作。

必须区分:

1
2
3
Local Interaction Feedback

Remote Application State Change

现代 optimistic UI 同样需要处理这种边界。

从今天的视角重新看这篇 RFC

一、它在解决“Local Fast Path vs Remote Slow Path”

RFC 5 最现代的地方,不是语法。

而是:

1
2
哪些行为必须去远端?
哪些行为可以本地完成?

DEL 的答案是:

1
2
3
4
5
6
7
8
9
10
11
Immediate Feedback
Simple Translation
Display Management

Local

Application Semantics
Shared Remote State
Heavy Computation

Remote

这个问题今天仍然出现在:

  • Web 应用;
  • 云游戏;
  • Remote IDE;
  • RDP/VNC;
  • Edge Computing;
  • Collaborative Editor;
  • Mobile App;
  • AI Agent UI。

网络快了很多,但:

1
local function call

依旧通常比:

1
cross-network round trip

便宜。

二、它很像 Code on Demand,但不是“下载任意可执行文件”

DEL 的关键策略是:

1
2
3
4
5
Server 提供 symbolic program

Client Site compile

与 local standard library 配合运行

如果用现代架构词汇描述,它很像:

1
2
3
4
5
portable code artifact
+
local runtime
+
local compilation

但其目标非常专用:

1
network interaction translation

而不是一门通用的应用分发平台。

三、NST 很像“公共 Runtime + App-specific Module”

RFC 5 要求每个 node 只实现一次 NST Library。

不同服务不再把所有底层适配代码重复一遍,而是只提供自己的 DEL program。

架构上可以抽象成:

1
2
3
4
5
6
7
+-----------------------------+
| NLS-specific DEL Program |
+-----------------------------+
| Common NST Runtime |
+-----------------------------+
| Local Host / Device Support |
+-----------------------------+

这种:

1
2
3
Stable Runtime
+
Downloadable Module

模式今天依然非常常见。

四、UHR 在解决“中间表示”问题

两个异构系统之间转换,有两种典型策略。

方案 A:两两转换

1
2
3
4
5
A ↔ B
A ↔ C
A ↔ D
B ↔ C
...

方案 B:公共中间表示

1
2
3
4
A ↔ IR
B ↔ IR
C ↔ IR
D ↔ IR

RFC 5 的 Universal Hardware Representation 本质上选择了第二种。

今天同样的结构大量存在:

1
2
3
4
5
6
7
8
Compiler IR
AST
Unicode
JSON Data Model
DOM
Scene Graph
Canonical Schema
Intermediate Event Model

它们并不是 DEL 的直接后代,但都利用了一个共同技巧:

不要让所有参与方互相理解;让所有参与方共同理解一个中间抽象。

五、服务器应该传“语义”,还是传“像素”

RFC 5 的直线例子非常值得今天重新看。

远程 UI 有两个极端:

Pixel / Device Streaming

1
2
3
4
5
Server 已经画好

传 Pixel / Low-level Drawing Command

Client 显示

Semantic UI

1
2
3
Server 说“这是一条线 / 一个对象 / 一个命令状态”

Client 自己决定怎样渲染

RFC 5 明显偏向第二种。

现代远程系统仍然在这两种策略之间做取舍:

1
2
3
RDP / Video Stream
vs
HTML / DOM / Native UI Model

它们的差别最终还是:

1
2
3
4
5
6
Bandwidth
Latency
Local Capability
Compatibility
Semantic Richness
Security

六、DEL 甚至碰到了 Optimistic / Immediate UI 的核心边界

用户按键后,本地先立即反馈:

1
2
3
4
5
6
7
User Action

Local Feedback

Network Request

Server Processing

今天前端工程非常熟悉:

1
Optimistic UI

当然 RFC 5 没有定义现代 optimistic transaction rollback。

但核心 UX 原理是一样的:

不要把所有感知延迟都暴露给用户。

七、把应用代码下放,会把性能问题变成安全问题

1969 年的设计重点是:

1
如何减少网络和 TSS 负载?

今天如果做同样架构,第一个问题往往变成:

1
我为什么要运行远端发来的代码?

于是必须出现:

1
2
3
4
5
6
7
Sandbox
Wasm Runtime
Code Signing
Capability Security
Resource Quota
Origin Isolation
Permission Model

这是 DEL 与现代 Code-on-Demand 系统之间最重要的时代差异。

八、“本地编译”与今天 JIT / AOT / Wasm 的问题很像

RFC 5 选择 Symbolic Program,是为了:

1
让每个站点针对自己的机器优化

今天我们也会讨论:

1
2
3
4
5
6
7
Source Distribution
Bytecode
Intermediate Representation
JIT
AOT
Native Compilation
WebAssembly

核心问题始终是:

1
2
3
4
5
6
7
Portability
vs
Runtime Cost
vs
Native Performance
vs
Security

DEL 的答案属于 1969 年的硬件环境:

1
2
3
Portable Symbolic Language
→ Site Compiler
→ Native Code

九、它很早就暴露了“平台无关语言”的语义陷阱

RFC 5 一边追求 machine-independent,一边警告:

1
依赖机器字长和补码行为的人迟早会出问题。

这句话放到今天几乎不用改:

1
2
3
“能编译”

“跨平台语义完全一致”

软件开发者仍然会被:

  • byte order;
  • integer width;
  • overflow;
  • encoding;
  • floating-point;
  • alignment;

这些底层差异击中。

十、它是一种“应用特定协议由代码描述”的思路

传统协议是:

1
双方预先实现同一个固定 State Machine

RFC 8700 对 DEL 的历史概括更有意思:

他们设想 application-specific protocols,并把代码下载到用户站点。

也就是:

1
2
3
Protocol Behavior
不是完全预装
而是部分由远端发送的程序描述

今天我们可能会想到:

  • downloadable schema;
  • protocol plugins;
  • eBPF-like programmable data path;
  • Wasm plugins;
  • server-driven client;

但仍需强调,这些只是现代类比,不是直接继承关系。

十一、DEL 失败的地方同样有价值

Steve Crocker 在 RFC 8700 回顾:

当 BBN 的 Host-IMP Interface 规范到来后,NWG 的注意力转向更紧迫的低层协议,自动下载代码的宏大设想消退。

这是很经典的工程现实:

1
2
3
4
5
宏大的通用抽象

遇到基础设施尚未稳定

团队先解决最底层互通

RFC 5 提醒我们:

系统抽象层次必须匹配基础设施成熟度。

如果底层连接、流控、地址、Host-Host Protocol 都还没稳定,再设计通用可下载网络语言,很可能过早。

这篇 RFC 带来的影响

RFC 5 没有成为今天 Internet Protocol Stack 的组成部分。

不能画成:

1
2
3
4
5
DEL

TCP/IP

Web

这样的“线性祖先图”。

它的影响更适合从“思想和研究方向”来理解。

一、它把 RFC 1 中的 DEL 设想真正展开成了一套系统

RFC 1 已经提出:

1
2
3
SRI 提供 DEL Front End
远端站点运行 DEL
降低交互延迟

RFC 5 则真正回答:

1
2
3
4
5
6
7
8
9
DEL 要运行在哪里?
公共 Runtime 是什么?
设备如何抽象?
程序怎样下载?
为什么传 Symbolic Form?
用户输入怎样编码?
服务端输出怎样解码?
显示数据怎样结构化?
语言需要哪些语法?

所以 RFC 5 可以看作早期 DEL 思路最完整的一次展开。

二、DEL 后续演化为更一般的 NIL 设想

RFC 8700 明确说:

1
2
first version  → DEL
later version → NIL

1970 年的 RFC 51《Proposal for a Network Interchange Language》 进一步提出:

Network Machine(网络机器)

RFC 100 对 NIL 的总结是:

1
2
把整个 Computer Network
看成一个抽象 Computing Facility

并用多个 sublanguage 描述:

  • Control;
  • Operation;
  • Data Declaration;
  • Environment。

也就是说,DEL 最初聚焦:

1
终端和交互适配

NIL 则开始走向:

1
更一般的 Network Computing Abstraction

三、RFC 100 证明这条研究路线至少持续到了 1971 年

RFC 100 在 D.4 中专门设置:

1
NIL, DEL, and Form Machines

并总结 DEL:

1
2
3
4
5
6
7
前端 Translator
字符集转换
返回消息本地转换
Immediate Feedback 本地处理
支持大型 Display-oriented System
Universal Hardware Representation
包含语言 Syntax

这说明 RFC 5 并不是发表以后马上无人问津。

它进入了早期 NWG 关于:

1
2
3
Network Data Transformation
Interactive Front End
Network Language

的一整条讨论线。

四、它很早就提出“把计算移向用户”

RFC 5 写:

1
2
responsibility for real-time display manipulation
may shift closer to the user

这是整篇最值得记住的技术判断之一。

今天我们把计算移动到:

1
2
3
4
5
Browser
Mobile Device
Edge Node
CDN Worker
GPU Client

通常也是为了:

1
2
3
4
降低延迟
减少中心负载
利用本地能力
改善交互体验

DEL 当然不是这些架构的直接来源,但它面对的是同一类分布式系统取舍。

五、它提供了一个非常早的 Code-on-Demand 历史案例

RFC 2555 中,Steve Crocker 回忆:

1
2
3
4
5
6
7
session begin

download small interpretative program

local interaction control

efficient use of narrow bandwidth

并把 Jeff Rulifson 的 DEL 视为这一思路的实现尝试。

1999 年回顾时,他直接提到了:

1
2
Java
ActiveX

所以从互联网自身的官方历史叙述看,DEL 的确长期被记忆为一种:

远端下发程序、本地执行、协助网络交互的早期构想。

六、它留下了“中间表示优于两两适配”的经典架构思想

Universal Hardware Representation 解决的是:

1
heterogeneous endpoints

之间的组合爆炸。

这种问题今天仍然存在:

1
2
3
4
数据库 A ↔ 数据库 B
语言 A ↔ 语言 B
协议 A ↔ 协议 B
设备 A ↔ 设备 B

常见解决方式仍然是:

1
2
3
Canonical Model
Intermediate Representation
Common Schema

RFC 5 是这类思路在早期网络交互中的一个很鲜明案例。

七、它把“显示协议”从设备命令提高到了逻辑实体

RFC 5 的:

1
2
不要发 500 个短 Vector
而要表达“一条直线”

是一种非常重要的抽象升级。

它把通信接口从:

1
How hardware draws

提升到:

1
What user should see

这种“传意图而不是传实现细节”的思想,在现代 API 与分布式 UI 设计中仍然非常有生命力。

八、它也展示了互联网设计并不是一条直线

RFC 5 最有历史价值的地方之一,是提醒我们:

互联网并不是从 NCP 一步一步“必然”升级成 TCP/IP,再“必然”出现 Web。

早期工程师同时探索过很多路线:

1
2
3
4
5
6
7
8
Host-Host Protocol
DEL
NIL
Form Machine
Message Description Language
TELNET
Network Graphics
File Transfer

有些成为主流。

有些被替代。

有些概念几十年以后以完全不同的技术形式再次出现。

RFC 5 就属于第三种中特别有意思的一篇。

总结

RFC 5 表面上是一份:

Decode Encode Language Specification

但真正读进去以后,会发现它想解决的不是“怎样发明一门新语言”这么简单。

它面对的是一个完整的分布式交互问题:

1
2
3
4
5
6
7
8
用户终端互不相同
Host 架构互不相同
字符集不同
显示设备不同
网络很慢
远端 TSS 很贵
交互需要即时反馈
应用还在快速演化

RFC 5 给出的整体答案是:

1
2
3
4
5
6
7
8
9
10
11
12
13
Universal Hardware Representation
+
Network Standard Translator
+
Downloadable DEL Symbolic Program
+
Local Compilation
+
Encode / Decode Translation
+
Local Immediate Feedback
+
Semantic Display Representation

其中几个关键设计尤其值得记住。

第一,不要为每一对异构设备都写一套转换器

1
2
3
4
5
Local Hardware

Universal Representation

Remote Semantics

第二,不要让所有交互都跨网络往返

1
2
Immediate Feedback → Local
Real Application Work → Remote

第三,不要只传某台设备的低层命令

1
2
3
“一条直线”
优于
“500 个短 Vector”

第四,不要把远程适配逻辑永久硬编码在每个用户站点

1
2
3
4
5
Server sends Symbolic DEL Program

User Site Compiles It

Local Runtime Executes It

第五,语言本身必须理解网络和交互

DEL 因此把:

1
2
3
4
5
6
Message
Buffer
Display
Tree
Coroutine
Pipe

都直接放进语言模型。

它最终没有成为 ARPANET 的通用执行环境。

随着 Host-IMP Interface 和更底层 Host-Host Protocol 问题变得紧迫,早期自动下载代码的宏大设计逐渐退居次要位置;之后这条思路又继续演化为 RFC 51 的 NIL,以及其他 Network Language / Form Machine 研究。

但 Steve Crocker 三十年、五十年后的两次 RFC 历史回顾仍然专门提到了 DEL。

原因并不难理解。

因为它在 1969 年就问出了一个今天仍然非常现代的问题:

如果网络另一端拥有服务和状态,而用户这一端拥有屏幕、输入设备和低延迟执行能力,那么到底应该把哪些逻辑放在服务器,哪些逻辑放在客户端,又应该用什么可移植形式把两端连接起来?

今天我们会用:

1
2
3
4
5
6
7
Browser
JavaScript
WebAssembly
Remote UI
Edge Runtime
Smart Client
Server-driven UI

回答不同版本的这个问题。

RFC 5 的答案叫:

DEL

它没有成为最终答案。

但在互联网真正上线之前,就有人已经开始认真思考这个问题了。


RFC 5 带读:Decode Encode Language (DEL)——1969 年的可下载前端程序与跨终端交互
https://allendericdalexander.github.io/2026/08/15/rfc/rfc00005-decode-encode-language-del/
作者
AtLuoFu
发布于
2026年8月15日
许可协议