在 8 位微控制器上托管网站:极简网络课程
在现代云计算的世界里,服务器以数千个核心和太字节(TB)级别的 RAM 为衡量标准,而在做完全相反的事情时,会有一种颠覆性的乐趣。正如作者所言,在 8 位微控制器上托管网站是一件“愚蠢的事情”,但它是一堂理解互联网协议栈基础层的绝佳课程。
这个项目证明了,只要具备一定的创造力并愿意实现遗留协议,你就能将一个 1 美元的芯片变成一个功能齐全(尽管速度很慢)的 Web 服务器。
硬件:AVR64DD32
这个项目的核心是 AVR64DD32,它是 AVR DD 系列的一员。虽然它与 Arduino 板上随处可见的 Atmega328 类似,但 DD 系列在内存方面提供了更高的性价比,并且拥有更精简的外设。
技术规格:
- CPU: 单核 8 位 AVR @ 24 MHz
- RAM: 8 kB
- Flash: 64 kB
- EEPROM: 256 bytes
- Voltage: 1.8 - 5.5 Volts
- Cost: ~$1
解决连接问题
将微控制器连接到互联网面临着一个巨大的瓶颈:速度。标准的以太网 (10BASE-T) 运行在 10 Mbps,并使用 Manchester 编码,这意味着线路实际看到的速率是 20 Mbps。对于一个运行在 24 MHz 的 8 位 AVR——其 IO 引脚上限为 12 MHz——通过软件生成这种信号实际上是不可能的。
该项目没有依赖专门的以太网芯片,而是利用了在 RFC 1055 中定义的 Serial Line Internet Protocol (SLIP)。SLIP 是一种遗留标准,旨在通过串口链路运行网络,在拨号上网时代非常有名。
SLIP 的工作原理
SLIP 非常简单。它将数据包封装在 0xC0 字节中。为了处理包含 0xC0 字节的数据,它使用转义序列:0xDB 0xDC。同样,任何现有的 0xDB 字节都会被替换为 0xDB 0xDD。
在主机端,可以使用 slattach 命令轻松地将 USB 转串口适配器转换为网络接口,从而在现代 Linux 机器上实现:
stty -F /dev/ttyUSB0 115200 raw cs8
slattach -m -F -L -p slip /dev/ttyUSB0
实现网络协议栈
在建立物理链路后,微控制器仍需理解如何进行通信。这需要实现 IP 和 TCP 层。
IP 层
实现 IPv4 出奇地简单,因为现代操作系统已在很大程度上禁用了数据包分片。MCU 只需要交换接收到的数据包的源地址和目的地址以生成响应头,并重置生存时间 (TTL) 计数器。
TCP 层
TCP 是复杂性所在。与 IP 不同,TCP 是有状态的。微控制器必须跟踪连接状态,处理丢失数据包的定期重传,并管理众多边缘情况以确保可靠交付。
HTTP 层
为了节省资源,作者绕过了完整的 HTTP 实现。相反,服务器被编程为:只要网站上只有一个 URL,无论请求是什么,它都会发送一个硬编码的响应。
路由与公共访问
由于 MCU 缺乏公网可路由的 IPv4 地址且位于 NAT 之后,作者采用了混合路由策略:
- WireGuard: 在本地 Linux 路由器和数据中心的一台 VPS 中创建了一个虚拟网络链路。
- Reverse Proxy: VPS 被配置为代理特定路径(例如
/mcu)下的请求到 MCU 的本地地址块。
这种设置保护了 MCU 脆弱的 TCP/IP 协议栈免受互联网开放环境的直接暴露,否则考虑到串口连接的“拨号”速度,这很容易受到 DDoS 攻击。
用户体验
其结果是一个能唤起怀旧感的网站。由于带宽非常有限,页面的加载方式反映了早期互联网时代的特征。正如一位观察者所言:
"I love how I can see the HTML being streamed onto the 页面上实时流式传输,就像拨号上网的旧时光,图片从上到下逐渐渲染的场景。"
通过剥离现代 Web 开发的抽象层,这个项目突显了互联网核心协议的优雅,以及我们已经习惯于将其视为标准的庞大开销。