cweb不是网站某个官方框架,也不是教程什么新出的编译器。它是网站我自己攒的一套网站开发流程,核心就一句话:用C语言写后端逻辑,教程编译成原生二进制,网站前端该用HTML还是教程HTML,中间靠CGI或者FastCGI对接。网站听起来老派?教程对,但快得离谱。网站
去年帮朋友搞一个物联网设备管理后台,教程设备端上报数据用的网站是C写的采集程序,服务端本来想用Python Flask糊一个,教程结果压测一跑,网站单机两千并发就喘得不行。教程后来换成C写CGI,网站同样的硬件,轻松扛到八千。这不是Python不行,是场景不对——高并发、低延迟、逻辑又不复杂的接口,C直接上反而省事。
环境准备:别急着装一堆东西
你需要一个Linux环境,Ubuntu或者Debian都行。编译器用gcc,Web服务器我习惯用lighttpd,比nginx轻,配置CGI也直观。别用Apache,那套配置能把你绕晕。装好之后,在
/var/www/cgi-bin/下放编译好的可执行文件,权限给755,lighttpd配置里打开cgi.assign = ( "" => "" ),完事。写个最简单的例子。新建
hello.c:#include <stdio.h> int main(void) { printf("Content-Type: text/html\n\n"); printf("<h1>Hello from C</h1>"); return 0; }编译:
gcc -o hello.cgi hello.c。扔进cgi-bin,浏览器访问/cgi-bin/hello.cgi,页面就出来了。注意那个\n\n,HTTP头和正文必须空一行隔开,少一个换行都不行。我第一次写的时候漏了,浏览器直接下载文件,排查了半小时。处理表单和查询字符串
CGI程序通过环境变量拿数据。GET请求的参数在
QUERY_STRING里,POST的正文长度在CONTENT_LENGTH,从标准输入读。写个解析函数,把key=value&key2=value2这种格式拆开。别用strtok,它会改原字符串,用strchr和strncpy自己手动切更稳。URL编码要处理。
%20转空格,+也转空格。写个urldecode函数,二十行搞定。别小看这个,中文参数不解码直接乱码,用户提交个带空格的搜索词就崩。连接数据库:别用ORM,直接上libpq或者mysqlclient
C没有好用的ORM,也不需要有。PostgreSQL的libpq库,几行代码就能连:
PGconn *conn = PQconnectdb("host=localhost dbname=test user=postgres"); PGresult *res = PQexec(conn, "SELECT id, name FROM users"); for (int i = 0; i < PQntuples(res); i++) { printf("<li>%s</li>", PQgetvalue(res, i, 1)); }记得
PQclear(res)和PQfinish(conn),不然内存泄漏。C写Web最烦的就是这个,每分配一块内存都得想着释放。但反过来想,你完全掌控了资源,没有GC停顿,没有隐藏开销。模板怎么办?自己拼字符串
别指望在C里搞什么模板引擎。我的做法是:HTML片段写成
const char*数组,用snprintf往缓冲区里填。缓冲区开大点,比如64KB,够用了。注意snprintf的返回值,如果大于缓冲区大小说明被截断了,得处理。一个实际例子:设备列表页。从数据库查出设备名和状态,循环里
snprintf(buf + offset, size - offset, "<tr><td>%s</td><td>%s</td></tr>", name, status),offset累加。简单粗暴,但跑起来飞快。性能调优:几个关键点
CGI每次请求都fork一个新进程,开销不小。换FastCGI,进程常驻,性能提升一个数量级。lighttpd配
mod_fastcgi,C程序里用libfcgi的FCGI_Accept()循环处理请求。改起来不难,但效果立竿见影。数据库连接别每次请求都新建。在FastCGI进程初始化时建好连接池,请求来了直接取。连接池用数组加互斥锁实现,简单有效。
输出缓冲区设大点。
setvbuf(stdout, NULL, _IOFBF, 65536),减少系统调用次数。适用场景和坑
cweb这套东西适合:API网关、物联网数据接收、高频交易后台、嵌入式设备管理界面。不适合:内容管理系统、电商前台、任何需要快速迭代业务逻辑的项目。C的开发效率摆在那,改个字段要重新编译部署,产品经理能急死。
内存安全是最大的坑。缓冲区溢出、野指针、双重释放,每一个都能让服务器崩掉。用
valgrind跑测试,用-fsanitize=address编译调试版本。生产环境开-O2,但别开-O3,有时候会出诡异问题。还有,C写Web没有现成的会话管理、没有CSRF防护、没有输入过滤库。这些都得自己写。写好了是护城河,写不好是灾难。我一般只把cweb用在内部服务或者对性能极度敏感的接口上,对外Web应用还是老老实实用成熟框架。
最后说个真事:那个物联网后台跑了快一年,日均处理三百万请求,内存占用稳定在12MB。同事问我用的什么黑科技,我说就是C加FastCGI,他愣了半天。
顶: 813踩: 5






评论专区