返回

文章详情

现代C语言网络应用

Hacker News2026年10月12日 16:13

# Corey Prophitt » 现代C语言网络应用 ## 引言 如果你在1994年想要一个动态网站,你就得写一个C程序,将其放入cgi-bin目录,并让Apache根据请求进行分叉。三十二年后,我使用基本上相同的技术发布了一款商业网络产品。marketyour.games的一切都很现代。它是一个具有用户账户的网络产品,为内容创作者提供一个搜索仪表板,有用于整理的文件夹,通过Stripe进行支付和通过Postmark发送交易邮件。它遵循渐进增强,并且不需要任何JavaScript。除制作方式和服务方式外,一切都很现代。以下是我在2026年用C语言编写真实产品并通过CGI提供服务的想法。 ## 摘要 CGI在2004年的衰退是合理的,但在2026年并不能成立。你可以用C语言编写现代网络应用。我发布了一个。一个二进制文件,一个SQLite文件,三个依赖项,整个事情都可以在你脑海中装下。 ## 实现方式 栈是BCHS:OpenBSD、C、httpd和SQLite。没有框架。你编写一个读取CGI环境变量并作出响应的C程序。没有模板语言。你编写输出HTML的C代码。没有单独的数据库服务器。你通过SQLite的C API打开数据库文件。没有容器。你构建一个静态链接的二进制文件并将其放入一个文件夹中。每个请求都启动一个新的进程。部署新版本只是替换一个文件。这意味着没有服务器重启和停机时间。新请求将自动使用新二进制文件。OpenBSD拥有合理的默认设置,并提供了实际保护C程序的工具,如pledge和unveil。Httpd默认从chroot中服务,因此你的CGI二进制文件运行在文件系统的自己的角落中。我依赖于三个额外的库:libcurl处理所有对Stripe和Postmark的出站请求。libsodium处理随机标识符生成、密码散列和Stripe Webhook的HMAC验证。libcjson处理Stripe和Postmark的JSON解析。只有其中两个是实际的构建依赖:libcurl和libsodium。libcjson是一个单独的C文件,没有外部依赖。SQLite提供官方的合并构建(单个C文件)。它们都是被打包并作为项目的一部分构建。结果是构建几乎没有移动部件。干净的构建只需几秒钟,完成重建不到半秒钟。与传统的静态资产提供方式不同,我将所有流量从httpd转发到CGI二进制文件。每个资产都被编译进可执行文件并从内存中提供。 ## 我喜欢的地方 基础优于框架。CGI不是一个需要学习的框架。1.1规范在2004年发布,自那以后没有变化。没有需要内化的API。整个接口只包含一些基本的HTTP概念:请求头、请求方法、查询字符串、请求体数据。如果你理解HTTP,你就已经理解了CGI。它是语言和平台无关的。你只需学一次,这些知识将永远有效。 清晰的关注点分离。现代网络应用通常在前面放置像nginx这样的网络服务器,并反向代理到用其他语言(如Ruby、Python、Go或Rust)编写的应用服务器。这对我来说总是有点奇怪:你本质上有两个网络服务器,其中一个还负责你的业务逻辑。CGI给了你一个单一的网络服务器,直接调用你的业务逻辑。清楚地知道谁做什么。这也使调试更简单。你的应用程序是一个普通程序,你可以从shell中运行:向它输入请求,观察stderr,使用gdb逐步执行。从某种意义上说,CGI类似于无服务器架构:一个监控程序为每个请求调用你的代码,向其传递一包环境变量,并收集结果。CGI是无服务器的,减去供应商(和意外账单)。 最小的供应链风险。随着自主代理的崛起和每周对包仓库的攻击,拥有很少的依赖关系使人感到安慰。大多数现代技术栈都配有包管理器和相应的生态系统。这很方便,但依赖图膨胀。一个或两个直接依赖可以引入数百个间接依赖,每个依赖都由一个你从未听说的人维护,其发布凭证由自2015年以来重复使用的密码保护。我的供应链是一个C编译器和三个库。要破坏它,必须要破坏libcurl……这是一个整个互联网都在关注的项目,而不是一个每周只有十一次下载的包,且所有者已于2019年离开。 简单的工具。我内心是个极简主义者。我使用零插件的经典Vim。这意味着没有LSP、没有自动补全、没有代码格式化工具,以及没有AI。复杂的技术栈需要复杂的工具:它们需要语言服务器来穿越抽象层。但这个技术栈简单到只需一个普通的编辑器就足够了。整个应用程序是一个C文件和一个Makefile的目录。打开一个文件,读取它,你就会知道它的作用。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

☕请我喝杯咖啡