首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

嵌入式Web開發實戰:C語言CGI程序設計全攻略

     編輯:關於C語言

前言:從 Java Web 到嵌入式 CGI 的思維轉變

作者從 Java Web 轉型嵌入式開發,面臨記憶體受限(Flash 僅 1MB)、無 GC、需手動管理資源等挑戰。本文系統整理 CGI(Common Gateway Interface)在嵌入式 Linux(lighttpd)環境下的原理、關鍵環境變量、表單解析、HTML 輸出與調試技巧,助你快速上手嵌入式 Web 介面開發。

一、CGI 核心原理

1. 什麼是 CGI?

CGI 定義了 Web Server(如 lighttpd)調用外部可執行程式的標準協議。流程:

  1. 瀏覽器發送 HTTP 請求(含表單數據)。
  2. Web Server 啟動 CGI 程式,將數據通過 標準輸入(stdin)、環境變量 傳遞給 CGI。
  3. CGI 處理邏輯,結果通過 標準輸出(stdout) 回傳給 Web Server,再轉給瀏覽器。

C 語言 CGI 優勢:編譯執行、二進制不可篡改、執行速度快、佔用資源極低——極適合嵌入式場景。

2. CGI 三大介面

介面用途典型場景
標準輸入 (stdin)接收 POST 數據流表單提交、檔案上傳
環境變量傳遞請求元數據QUERY_STRING (GET)、CONTENT_LENGTH、HTTP_COOKIE
標準輸出 (stdout)輸出 HTTP 響應MIME Head + HTML/JSON/圖片二進制

二、關鍵環境變量速查表

REQUEST_METHOD   : GET / POST
CONTENT_LENGTH   : POST 數據長度(字節數,必讀,否則無法知曉輸入結束)
CONTENT_TYPE     : application/x-www-form-urlencoded (表單預設)
QUERY_STRING     : GET 參數 / POST 也可能攜帶
HTTP_COOKIE      : 客戶端 Cookie
REMOTE_ADDR      : 客戶端 IP
SCRIPT_NAME      : CGI 程式路徑

三、極簡 CGI 範例:回顯 POST 數據

#include <stdio.h>
#include <stdlib.h>

int main() {
    char *lenStr = getenv("CONTENT_LENGTH");
    int n = lenStr ? atoi(lenStr) : 0;

    // 1. 輸出 MIME Head(雙換行結束 header)
    printf("Content-Type: text/plain\r\n\r\n");

    // 2. 讀取 stdin 並原樣輸出
    for (int i = 0; i < n; ++i) {
        int ch = getchar();
        if (ch == EOF) break;
        putchar(ch);
    }
    fflush(stdout);
    return 0;
}

關鍵點:CONTENT_LENGTH 必讀,因 stdin 無 EOF 終止;雙 \r\n 分隔 Header 與 Body。

四、表單數據解析:URL 編碼處理

表單提交格式:name1=value1&name2=value2。特殊字符編碼:

  • + → 空格
  • %XX → 十六進制 ASCII(如 %20 = 空格,%3D = =)

完整解析器實作(單檔、無依賴)

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int hexVal(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    return 0;
}

int main() {
    char *lenStr = getenv("CONTENT_LENGTH");
    int n = lenStr ? atoi(lenStr) : 0;

    printf("Content-Type: text/plain\r\n\r\n");

    for (int i = 0; i < n; ++i) {
        int ch = getchar();
        if (ch == EOF) break;

        switch (ch) {
            case '&':  putchar('\n'); break;          // 鍵值對換行
            case '+':  putchar(' '); break;           // + 轉空格
            case '%':  // %XX 解碼
                if (i + 2 < n) {
                    int h1 = hexVal(getchar());
                    int h2 = hexVal(getchar());
                    putchar((h1 << 4) | h2);
                    i += 2;
                }
                break;
            case '=':  putchar(':'); putchar(' '); break; // 美化輸出
            default:   putchar(ch);
        }
    }
    fflush(stdout);
    return 0;
}

五、輸出 HTML 頁面

只需將 MIME Head 改為 text/html,後續 printf 輸出標準 HTML:

printf("Content-Type: text/html\r\n\r\n");
printf("嵌入式 CGI Demo");
printf("

Hello from C CGI!

"); printf("

當前時間: %s

", __TIME__); printf(""); fflush(stdout);

六、嵌入式開發避坑指南

  1. 記憶體:禁用 malloc 大塊分配,用靜態緩衝區、棧上陣列;字串操作用 snprintf 防溢出。
  2. 並發:lighttpd 預設 mod_cgi 每請求 fork 一進程,嵌入式 CPU 弱,避免複雜計算;考慮 FastCGI(持久進程)提升效能。
  3. 調試:strace -f -p `pidof lighttpd` 追蹤 CGI 啟動;CGI 內用 openlog/syslog 寫系統日誌;或重定向 stderr 到檔案 freopen("/tmp/cgi.log","w",stderr)。
  4. 安全:嚴格驗證所有輸入長度、轉義輸出防 XSS;system()、popen() 禁用,防命令注入。

七、總結

C 語言 CGI 是嵌入式 Web 介面的基石。掌握 stdin/環境變量/stdout 三元組、URL 解碼、MIME Head 規範,即可構建輕量、高效、安全的設備管理頁面。建議進階學習 FastCGI、cJSON(JSON 生成/解析)、libmicrohttpd(內嵌 HTTP Server)以應對更複雜場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved