引言

在当今的互联网时代,Web服务已经成为软件系统中不可或缺的一部分。C语言作为一门高效、底层且性能卓越的编程语言,在构建高性能Web服务方面具有独特的优势。本文将从零开始,详细指导你如何使用C语言构建一个高效、稳定的Web服务系统。

1. 项目准备与环境搭建

1.1 开发环境选择

在开始之前,我们需要选择合适的开发环境。推荐使用以下工具:

  • 操作系统:Linux(Ubuntu/CentOS)或macOS,Windows用户可以使用WSL2
  • 编译器:GCC或Clang
  • 构建工具:Make或CMake
  • 版本控制:Git

1.2 安装必要的库

C语言本身不直接支持网络编程和HTTP协议,我们需要借助第三方库。以下是几个常用的选择:

  • libcurl:用于HTTP客户端(测试用)
  • libmicrohttpd:轻量级HTTP服务器库
  • libevent:事件驱动网络编程库
  • OpenSSL:用于HTTPS支持

在Ubuntu上安装这些库:

sudo apt-get update
sudo apt-get install build-essential libmicrohttpd-dev libevent-dev libcurl4-openssl-dev libssl-dev

1.3 项目结构设计

一个良好的项目结构有助于代码的组织和维护。建议的项目结构如下:

c-webservice/
├── src/                 # 源代码目录
│   ├── main.c          # 主程序入口
│   ├── server.c        # 服务器核心逻辑
│   ├── request.c       # 请求处理模块
│   ├── response.c      # 响应生成模块
│   └── utils.c         # 工具函数
├── include/             # 头文件目录
│   ├── server.h
│   ├── request.h
│   ├── response.h
│   └── utils.h
├── tests/               # 测试代码
├── docs/                # 文档
├── Makefile             # 构建脚本
└── README.md            # 项目说明

2. HTTP协议基础

2.1 HTTP请求结构

HTTP请求由三部分组成:

  1. 请求行:包含方法、URL和HTTP版本
  2. 请求头:键值对形式的元数据
  3. 请求体:可选的数据部分

示例请求:

GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: application/json

2.2 HTTP响应结构

HTTP响应同样由三部分组成:

  1. 状态行:包含HTTP版本、状态码和状态描述
  2. 响应头:键值对形式的元数据
  3. 响应体:实际返回的数据

示例响应:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 42

{"status": "success", "data": {"id": 1, "name": "John"}}

3. 基础服务器实现

3.1 使用libmicrohttpd创建HTTP服务器

libmicrohttpd是一个轻量级的HTTP服务器库,适合快速原型开发。

示例代码:hello_server.c

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

#define PORT 8080

// 处理HTTP请求的回调函数
static int handle_request(void *cls, struct MHD_Connection *connection,
                         const char *url, const char *method,
                         const char *version, const char *upload_data,
                         size_t *upload_data_size, void **con_cls) {
    
    // 只处理GET请求
    if (strcmp(method, "GET") != 0) {
        return MHD_NO;
    }
    
    // 简单的响应
    const char *response_str = "{\"message\": \"Hello, World!\"}";
    struct MHD_Response *response = MHD_create_response_from_buffer(
        strlen(response_str),
        (void*)response_str,
        MHD_RESPMEM_MUST_COPY
    );
    
    // 设置响应头
    MHD_add_response_header(response, "Content-Type", "application/json");
    
    // 发送响应
    int ret = MHD_queue_response(connection, MHD_OK, response);
    MHD_destroy_response(response);
    
    return ret;
}

int main() {
    struct MHD_Daemon *daemon;
    
    // 创建HTTP服务器
    daemon = MHD_start_daemon(
        MHD_USE_INTERNAL_POLLING_THREAD,
        PORT,
        NULL, NULL,
        &handle_request, NULL,
        MHD_OPTION_END
    );
    
    if (daemon == NULL) {
        fprintf(stderr, "Failed to start server on port %d\n", PORT);
        return 1;
    }
    
    printf("Server running on http://localhost:%d\n", PORT);
    printf("Press Ctrl+C to stop\n");
    
    // 等待用户中断
    getchar();
    
    // 停止服务器
    MHD_stop_daemon(daemon);
    
    return 0;
}

编译和运行:

gcc -o hello_server hello_server.c -lmicrohttpd
./hello_server

3.2 使用libevent实现高性能服务器

libevent是一个事件驱动的网络库,适合构建高并发的Web服务。

示例代码:event_server.c

#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define PORT 8080

// HTTP请求处理回调
void http_request_handler(struct evhttp_request *req, void *arg) {
    // 获取请求方法
    const char *method = evhttp_request_get_command(req);
    
    // 只处理GET请求
    if (method != EVHTTP_REQ_GET) {
        evhttp_send_error(req, HTTP_BADMETHOD, "Method Not Allowed");
        return;
    }
    
    // 获取请求URI
    const char *uri = evhttp_request_get_uri(req);
    printf("Received request for: %s\n", uri);
    
    // 创建响应缓冲区
    struct evbuffer *evb = evbuffer_new();
    
    // 根据URI返回不同内容
    if (strcmp(uri, "/api/hello") == 0) {
        evbuffer_add_printf(evb, "{\"message\": \"Hello from libevent!\"}");
        evhttp_add_header(evhttp_request_get_output_headers(req), 
                         "Content-Type", "application/json");
    } else if (strcmp(uri, "/api/status") == 0) {
        evbuffer_add_printf(evb, "{\"status\": \"running\", \"uptime\": 1234}");
        evhttp_add_header(evhttp_request_get_output_headers(req), 
                         "Content-Type", "application/json");
    } else {
        evbuffer_add_printf(evb, "{\"error\": \"Not Found\"}");
        evhttp_add_header(evhttp_request_get_output_headers(req), 
                         "Content-Type", "application/json");
    }
    
    // 发送响应
    evhttp_send_reply(req, HTTP_OK, "OK", evb);
    
    // 释放缓冲区
    evbuffer_free(evb);
}

int main() {
    struct event_base *base;
    struct evhttp *http;
    
    // 创建事件基础
    base = event_base_new();
    if (!base) {
        fprintf(stderr, "Failed to create event base\n");
        return 1;
    }
    
    // 创建HTTP服务器
    http = evhttp_new(base);
    if (!http) {
        fprintf(stderr, "Failed to create HTTP server\n");
        event_base_free(base);
        return 1;
    }
    
    // 绑定到端口
    if (evhttp_bind_socket(http, "0.0.0.0", PORT) != 0) {
        fprintf(stderr, "Failed to bind to port %d\n", PORT);
        evhttp_free(http);
        event_base_free(base);
        return 1;
    }
    
    // 设置请求处理回调
    evhttp_set_gencb(http, http_request_handler, NULL);
    
    printf("Server running on http://localhost:%d\n", PORT);
    printf("Endpoints:\n");
    printf("  GET /api/hello\n");
    printf("  GET /api/status\n");
    printf("Press Ctrl+C to stop\n");
    
    // 进入事件循环
    event_base_dispatch(base);
    
    // 清理资源
    evhttp_free(http);
    event_base_free(base);
    
    return 0;
}

编译和运行:

gcc -o event_server event_server.c -levent
./event_server

4. 请求处理与路由

4.1 路由系统设计

一个完整的Web服务需要支持多个端点和不同的HTTP方法。我们需要设计一个路由系统来管理请求。

示例代码:router.c

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

// 路由处理函数类型
typedef void (*route_handler)(void *request, void *response);

// 路由结构体
typedef struct {
    char *method;           // HTTP方法:GET, POST, PUT, DELETE等
    char *path;             // 路径模式,支持通配符
    route_handler handler;  // 处理函数
} route_t;

// 路由表
typedef struct {
    route_t *routes;
    int count;
    int capacity;
} router_t;

// 初始化路由表
router_t* router_init() {
    router_t *router = malloc(sizeof(router_t));
    router->capacity = 10;
    router->count = 0;
    router->routes = malloc(sizeof(route_t) * router->capacity);
    return router;
}

// 添加路由
void router_add_route(router_t *router, const char *method, 
                     const char *path, route_handler handler) {
    if (router->count >= router->capacity) {
        router->capacity *= 2;
        router->routes = realloc(router->routes, sizeof(route_t) * router->capacity);
    }
    
    route_t *route = &router->routes[router->count];
    route->method = strdup(method);
    route->path = strdup(path);
    route->handler = handler;
    router->count++;
}

// 路径匹配(支持通配符)
bool path_match(const char *pattern, const char *path) {
    // 简单的精确匹配
    return strcmp(pattern, path) == 0;
}

// 查找匹配的路由
route_t* router_find_route(router_t *router, const char *method, 
                          const char *path) {
    for (int i = 0; i < router->count; i++) {
        route_t *route = &router->routes[i];
        if (strcmp(route->method, method) == 0 && 
            path_match(route->path, path)) {
            return route;
        }
    }
    return NULL;
}

// 释放路由表
void router_free(router_t *router) {
    for (int i = 0; i < router->count; i++) {
        free(router->routes[i].method);
        free(router->routes[i].path);
    }
    free(router->routes);
    free(router);
}

4.2 集成路由到服务器

将路由系统集成到之前的libevent服务器中:

示例代码:router_server.c

#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 引入路由系统
#include "router.c"

#define PORT 8080

// 全局路由表
router_t *global_router = NULL;

// 处理函数示例
void handle_hello(void *req, void *resp) {
    struct evhttp_request *request = (struct evhttp_request *)req;
    struct evbuffer *response = (struct evbuffer *)resp;
    
    evbuffer_add_printf(response, "{\"message\": \"Hello, World!\"}");
    evhttp_add_header(evhttp_request_get_output_headers(request), 
                     "Content-Type", "application/json");
}

void handle_users(void *req, void *resp) {
    struct evhttp_request *request = (struct evhttp_request *)req;
    struct evbuffer *response = (struct evbuffer *)resp;
    
    evbuffer_add_printf(response, 
        "{\"users\": [{\"id\": 1, \"name\": \"Alice\"}, {\"id\": 2, \"name\": \"Bob\"}]}");
    evhttp_add_header(evhttp_request_get_output_headers(request), 
                     "Content-Type", "application/json");
}

void handle_user_by_id(void *req, void *resp) {
    struct evhttp_request *request = (struct evhttp_request *)req;
    struct evbuffer *response = (struct evbuffer *)resp;
    
    // 从URI中提取ID(简化处理)
    const char *uri = evhttp_request_get_uri(request);
    int user_id = 1; // 实际应该解析URI获取ID
    
    evbuffer_add_printf(response, 
        "{\"user\": {\"id\": %d, \"name\": \"User %d\"}}", user_id, user_id);
    evhttp_add_header(evhttp_request_get_output_headers(request), 
                     "Content-Type", "application/json");
}

void handle_post_data(void *req, void *resp) {
    struct evhttp_request *request = (struct evhttp_request *)req;
    struct evbuffer *response = (struct evbuffer *)resp;
    
    // 获取请求体
    struct evbuffer *input = evhttp_request_get_input_buffer(request);
    size_t len = evbuffer_get_length(input);
    
    if (len > 0) {
        char *data = malloc(len + 1);
        evbuffer_copyout(input, data, len);
        data[len] = '\0';
        
        evbuffer_add_printf(response, 
            "{\"received\": true, \"data_length\": %zu, \"data\": \"%s\"}", 
            len, data);
        
        free(data);
    } else {
        evbuffer_add_printf(response, "{\"error\": \"No data received\"}");
    }
    
    evhttp_add_header(evhttp_request_get_output_headers(request), 
                     "Content-Type", "application/json");
}

// HTTP请求处理回调
void http_request_handler(struct evhttp_request *req, void *arg) {
    const char *method = evhttp_request_get_command(req);
    const char *uri = evhttp_request_get_uri(req);
    
    // 将方法转换为字符串
    const char *method_str = NULL;
    switch (method) {
        case EVHTTP_REQ_GET: method_str = "GET"; break;
        case EVHTTP_REQ_POST: method_str = "POST"; break;
        case EVHTTP_REQ_PUT: method_str = "PUT"; break;
        case EVHTTP_REQ_DELETE: method_str = "DELETE"; break;
        default: 
            evhttp_send_error(req, HTTP_BADMETHOD, "Method Not Allowed");
            return;
    }
    
    // 查找路由
    route_t *route = router_find_route(global_router, method_str, uri);
    
    if (route == NULL) {
        evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
        return;
    }
    
    // 创建响应缓冲区
    struct evbuffer *response = evbuffer_new();
    
    // 调用处理函数
    route->handler(req, response);
    
    // 发送响应
    evhttp_send_reply(req, HTTP_OK, "OK", response);
    
    // 释放缓冲区
    evbuffer_free(response);
}

int main() {
    struct event_base *base;
    struct evhttp *http;
    
    // 初始化路由表
    global_router = router_init();
    
    // 注册路由
    router_add_route(global_router, "GET", "/api/hello", handle_hello);
    router_add_route(global_router, "GET", "/api/users", handle_users);
    router_add_route(global_router, "GET", "/api/users/1", handle_user_by_id);
    router_add_route(global_router, "POST", "/api/data", handle_post_data);
    
    // 创建事件基础
    base = event_base_new();
    if (!base) {
        fprintf(stderr, "Failed to create event base\n");
        return 1;
    }
    
    // 创建HTTP服务器
    http = evhttp_new(base);
    if (!http) {
        fprintf(stderr, "Failed to create HTTP server\n");
        event_base_free(base);
        return 1;
    }
    
    // 绑定到端口
    if (evhttp_bind_socket(http, "0.0.0.0", PORT) != 0) {
        fprintf(stderr, "Failed to bind to port %d\n", PORT);
        evhttp_free(http);
        event_base_free(base);
        return 1;
    }
    
    // 设置请求处理回调
    evhttp_set_gencb(http, http_request_handler, NULL);
    
    printf("Server running on http://localhost:%d\n", PORT);
    printf("Endpoints:\n");
    printf("  GET  /api/hello\n");
    printf("  GET  /api/users\n");
    printf("  GET  /api/users/1\n");
    printf("  POST /api/data\n");
    printf("Press Ctrl+C to stop\n");
    
    // 进入事件循环
    event_base_dispatch(base);
    
    // 清理资源
    router_free(global_router);
    evhttp_free(http);
    event_base_free(base);
    
    return 0;
}

5. 请求解析与参数处理

5.1 URL参数解析

在实际应用中,URL经常包含查询参数,如/api/users?page=1&limit=10

示例代码:url_parser.c

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

// 解析URL查询参数
typedef struct {
    char *key;
    char *value;
} query_param_t;

typedef struct {
    query_param_t *params;
    int count;
    int capacity;
} query_params_t;

// 初始化查询参数容器
query_params_t* query_params_init() {
    query_params_t *params = malloc(sizeof(query_params_t));
    params->capacity = 10;
    params->count = 0;
    params->params = malloc(sizeof(query_param_t) * params->capacity);
    return params;
}

// 添加参数
void query_params_add(query_params_t *params, const char *key, 
                     const char *value) {
    if (params->count >= params->capacity) {
        params->capacity *= 2;
        params->params = realloc(params->params, 
                                sizeof(query_param_t) * params->capacity);
    }
    
    query_param_t *param = &params->params[params->count];
    param->key = strdup(key);
    param->value = strdup(value);
    params->count++;
}

// 解析URL查询字符串
query_params_t* parse_query_string(const char *query) {
    query_params_t *params = query_params_init();
    
    if (query == NULL || strlen(query) == 0) {
        return params;
    }
    
    char *query_copy = strdup(query);
    char *token = strtok(query_copy, "&");
    
    while (token != NULL) {
        char *equals = strchr(token, '=');
        if (equals != NULL) {
            *equals = '\0';
            char *key = token;
            char *value = equals + 1;
            
            // URL解码(简化版本)
            query_params_add(params, key, value);
        }
        
        token = strtok(NULL, "&");
    }
    
    free(query_copy);
    return params;
}

// 获取参数值
const char* query_params_get(query_params_t *params, const char *key) {
    for (int i = 0; i < params->count; i++) {
        if (strcmp(params->params[i].key, key) == 0) {
            return params->params[i].value;
        }
    }
    return NULL;
}

// 释放查询参数
void query_params_free(query_params_t *params) {
    for (int i = 0; i < params->count; i++) {
        free(params->params[i].key);
        free(params->params[i].value);
    }
    free(params->params);
    free(params);
}

5.2 集成到服务器

将URL参数解析集成到服务器中:

示例代码:server_with_params.c

#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 引入URL解析器
#include "url_parser.c"

#define PORT 8080

// 处理带参数的请求
void handle_paginated_users(void *req, void *resp) {
    struct evhttp_request *request = (struct evhttp_request *)req;
    struct evbuffer *response = (struct evbuffer *)resp;
    
    // 获取查询字符串
    const char *uri = evhttp_request_get_uri(request);
    const char *query = strchr(uri, '?');
    if (query != NULL) {
        query++; // 跳过'?'
    }
    
    // 解析查询参数
    query_params_t *params = parse_query_string(query);
    
    // 获取参数值
    const char *page_str = query_params_get(params, "page");
    const char *limit_str = query_params_get(params, "limit");
    
    int page = page_str ? atoi(page_str) : 1;
    int limit = limit_str ? atoi(limit_str) : 10;
    
    // 生成响应
    evbuffer_add_printf(response, 
        "{\"page\": %d, \"limit\": %d, \"total\": 100, \"users\": []}", 
        page, limit);
    
    evhttp_add_header(evhttp_request_get_output_headers(request), 
                     "Content-Type", "application/json");
    
    // 释放参数
    query_params_free(params);
}

// 处理路径参数(如 /api/users/{id})
void handle_user_with_id(void *req, void *resp) {
    struct evhttp_request *request = (struct evhttp_request *)req;
    struct evbuffer *response = (struct evbuffer *)resp;
    
    const char *uri = evhttp_request_get_uri(request);
    
    // 简单的路径参数提取(实际应用中需要更复杂的路由匹配)
    int user_id = 1;
    const char *path = uri;
    
    // 查找数字ID(简化处理)
    while (*path) {
        if (isdigit(*path)) {
            user_id = atoi(path);
            break;
        }
        path++;
    }
    
    evbuffer_add_printf(response, 
        "{\"user\": {\"id\": %d, \"name\": \"User %d\", \"email\": \"user%d@example.com\"}}", 
        user_id, user_id, user_id);
    
    evhttp_add_header(evhttp_request_get_output_headers(request), 
                     "Content-Type", "application/json");
}

int main() {
    // 这里可以集成到之前的服务器代码中
    // 为简洁起见,省略了完整的服务器设置代码
    printf("示例代码展示了如何处理URL参数和路径参数\n");
    return 0;
}

6. JSON数据处理

6.1 JSON库选择

C语言没有内置JSON支持,需要使用第三方库。推荐使用:

  • cJSON:轻量级,易于使用
  • Jansson:功能丰富,性能良好
  • json-c:稳定可靠

安装cJSON:

sudo apt-get install libcjson-dev

6.2 JSON序列化与反序列化

示例代码:json_handler.c

#include <cjson/cJSON.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 用户结构体
typedef struct {
    int id;
    char *name;
    char *email;
} user_t;

// 将用户结构体转换为JSON
char* user_to_json(user_t *user) {
    cJSON *root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "id", user->id);
    cJSON_AddStringToObject(root, "name", user->name);
    cJSON_AddStringToObject(root, "email", user->email);
    
    char *json_str = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);
    
    return json_str;
}

// 从JSON解析用户
user_t* json_to_user(const char *json_str) {
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL) {
        return NULL;
    }
    
    user_t *user = malloc(sizeof(user_t));
    user->id = cJSON_GetObjectItem(root, "id")->valueint;
    
    cJSON *name_item = cJSON_GetObjectItem(root, "name");
    user->name = strdup(name_item->valuestring);
    
    cJSON *email_item = cJSON_GetObjectItem(root, "email");
    user->email = strdup(email_item->valuestring);
    
    cJSON_Delete(root);
    return user;
}

// 创建用户数组的JSON
char* create_user_array_json() {
    cJSON *root = cJSON_CreateObject();
    cJSON *users = cJSON_CreateArray();
    
    // 添加多个用户
    for (int i = 1; i <= 3; i++) {
        cJSON *user = cJSON_CreateObject();
        cJSON_AddNumberToObject(user, "id", i);
        
        char name[20];
        snprintf(name, sizeof(name), "User%d", i);
        cJSON_AddStringToObject(user, "name", name);
        
        char email[50];
        snprintf(email, sizeof(email), "user%d@example.com", i);
        cJSON_AddStringToObject(user, "email", email);
        
        cJSON_AddItemToArray(users, user);
    }
    
    cJSON_AddItemToObject(root, "users", users);
    
    char *json_str = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);
    
    return json_str;
}

// 示例使用
void json_example() {
    // 创建用户
    user_t user = {
        .id = 1,
        .name = "Alice",
        .email = "alice@example.com"
    };
    
    // 转换为JSON
    char *json_str = user_to_json(&user);
    printf("User JSON: %s\n", json_str);
    
    // 解析JSON
    user_t *parsed_user = json_to_user(json_str);
    if (parsed_user) {
        printf("Parsed user: ID=%d, Name=%s, Email=%s\n", 
               parsed_user->id, parsed_user->name, parsed_user->email);
        free(parsed_user->name);
        free(parsed_user->email);
        free(parsed_user);
    }
    
    // 创建用户数组JSON
    char *array_json = create_user_array_json();
    printf("User array JSON: %s\n", array_json);
    
    free(json_str);
    free(array_json);
}

7. 数据库集成

7.1 数据库选择

对于C语言Web服务,常用的数据库有:

  • SQLite:轻量级,适合小型应用
  • PostgreSQL:功能强大,适合生产环境
  • MySQL:广泛使用,生态成熟

7.2 SQLite集成示例

示例代码:sqlite_handler.c

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

// 初始化数据库
int init_database(sqlite3 **db) {
    int rc = sqlite3_open("webservice.db", db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(*db));
        return -1;
    }
    
    // 创建用户表
    const char *create_table_sql = 
        "CREATE TABLE IF NOT EXISTS users ("
        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
        "name TEXT NOT NULL, "
        "email TEXT UNIQUE NOT NULL, "
        "created_at DATETIME DEFAULT CURRENT_TIMESTAMP);";
    
    char *err_msg = NULL;
    rc = sqlite3_exec(*db, create_table_sql, 0, 0, &err_msg);
    
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", err_msg);
        sqlite3_free(err_msg);
        return -1;
    }
    
    return 0;
}

// 插入用户
int insert_user(sqlite3 *db, const char *name, const char *email) {
    sqlite3_stmt *stmt;
    const char *sql = "INSERT INTO users (name, email) VALUES (?, ?);";
    
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
        return -1;
    }
    
    sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC);
    
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        return -1;
    }
    
    sqlite3_finalize(stmt);
    return 0;
}

// 查询用户
int query_users(sqlite3 *db, char ***names, char ***emails, int *count) {
    sqlite3_stmt *stmt;
    const char *sql = "SELECT name, email FROM users ORDER BY id;";
    
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
        return -1;
    }
    
    // 获取行数
    int row_count = 0;
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        row_count++;
    }
    
    // 重置语句
    sqlite3_reset(stmt);
    
    // 分配内存
    *names = malloc(sizeof(char*) * row_count);
    *emails = malloc(sizeof(char*) * row_count);
    *count = row_count;
    
    int i = 0;
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        const unsigned char *name = sqlite3_column_text(stmt, 0);
        const unsigned char *email = sqlite3_column_text(stmt, 1);
        
        (*names)[i] = strdup((const char*)name);
        (*emails)[i] = strdup((const char*)email);
        i++;
    }
    
    sqlite3_finalize(stmt);
    return 0;
}

// 示例使用
void sqlite_example() {
    sqlite3 *db;
    
    if (init_database(&db) != 0) {
        return;
    }
    
    // 插入测试数据
    insert_user(db, "Alice", "alice@example.com");
    insert_user(db, "Bob", "bob@example.com");
    
    // 查询用户
    char **names = NULL;
    char **emails = NULL;
    int count = 0;
    
    if (query_users(db, &names, &emails, &count) == 0) {
        printf("Users in database:\n");
        for (int i = 0; i < count; i++) {
            printf("  %d. %s (%s)\n", i+1, names[i], emails[i]);
            free(names[i]);
            free(emails[i]);
        }
        free(names);
        free(emails);
    }
    
    sqlite3_close(db);
}

8. 安全性考虑

8.1 输入验证

示例代码:input_validation.c

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>

// 邮箱验证
bool validate_email(const char *email) {
    if (email == NULL || strlen(email) == 0) {
        return false;
    }
    
    // 简单的邮箱验证(实际应用中需要更严格的验证)
    const char *at = strchr(email, '@');
    if (at == NULL) {
        return false;
    }
    
    const char *dot = strchr(at, '.');
    if (dot == NULL) {
        return false;
    }
    
    // 检查@和.的位置
    if (at > dot) {
        return false;
    }
    
    // 检查长度
    if (strlen(email) < 5 || strlen(email) > 100) {
        return false;
    }
    
    return true;
}

// SQL注入防护
char* escape_sql_string(const char *input) {
    if (input == NULL) {
        return NULL;
    }
    
    // 计算转义后长度
    size_t len = strlen(input);
    size_t escaped_len = len * 2 + 1; // 最坏情况
    
    char *escaped = malloc(escaped_len);
    char *p = escaped;
    
    for (size_t i = 0; i < len; i++) {
        switch (input[i]) {
            case '\'':
                *p++ = '\\';
                *p++ = '\'';
                break;
            case '\"':
                *p++ = '\\';
                *p++ = '\"';
                break;
            case '\\':
                *p++ = '\\';
                *p++ = '\\';
                break;
            default:
                *p++ = input[i];
        }
    }
    *p = '\0';
    
    return escaped;
}

// XSS防护
char* escape_html_string(const char *input) {
    if (input == NULL) {
        return NULL;
    }
    
    size_t len = strlen(input);
    size_t escaped_len = len * 6 + 1; // 最坏情况
    
    char *escaped = malloc(escaped_len);
    char *p = escaped;
    
    for (size_t i = 0; i < len; i++) {
        switch (input[i]) {
            case '&':
                strcpy(p, "&amp;");
                p += 5;
                break;
            case '<':
                strcpy(p, "&lt;");
                p += 4;
                break;
            case '>':
                strcpy(p, "&gt;");
                p += 4;
                break;
            case '"':
                strcpy(p, "&quot;");
                p += 6;
                break;
            case '\'':
                strcpy(p, "&#39;");
                p += 5;
                break;
            default:
                *p++ = input[i];
        }
    }
    *p = '\0';
    
    return escaped;
}

8.2 HTTPS支持

示例代码:https_server.c

#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define PORT 8443

// SSL上下文初始化
SSL_CTX* init_ssl_context() {
    SSL_CTX *ctx;
    
    // 初始化OpenSSL
    SSL_library_init();
    SSL_load_error_strings();
    OpenSSL_add_all_algorithms();
    
    // 创建SSL上下文
    ctx = SSL_CTX_new(TLS_server_method());
    if (ctx == NULL) {
        ERR_print_errors_fp(stderr);
        return NULL;
    }
    
    // 加载证书和私钥(需要预先生成)
    if (SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        SSL_CTX_free(ctx);
        return NULL;
    }
    
    if (SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        SSL_CTX_free(ctx);
        return NULL;
    }
    
    // 验证私钥
    if (!SSL_CTX_check_private_key(ctx)) {
        fprintf(stderr, "Private key does not match the certificate\n");
        SSL_CTX_free(ctx);
        return NULL;
    }
    
    return ctx;
}

// HTTPS请求处理
void https_request_handler(struct evhttp_request *req, void *arg) {
    // 处理逻辑与HTTP相同
    struct evbuffer *response = evbuffer_new();
    evbuffer_add_printf(response, "{\"message\": \"Secure Hello!\"}");
    evhttp_add_header(evhttp_request_get_output_headers(req), 
                     "Content-Type", "application/json");
    evhttp_send_reply(req, HTTP_OK, "OK", response);
    evbuffer_free(response);
}

int main() {
    struct event_base *base;
    struct evhttp *http;
    SSL_CTX *ssl_ctx;
    
    // 初始化SSL上下文
    ssl_ctx = init_ssl_context();
    if (ssl_ctx == NULL) {
        fprintf(stderr, "Failed to initialize SSL context\n");
        return 1;
    }
    
    // 创建事件基础
    base = event_base_new();
    if (!base) {
        fprintf(stderr, "Failed to create event base\n");
        SSL_CTX_free(ssl_ctx);
        return 1;
    }
    
    // 创建HTTP服务器
    http = evhttp_new(base);
    if (!http) {
        fprintf(stderr, "Failed to create HTTP server\n");
        event_base_free(base);
        SSL_CTX_free(ssl_ctx);
        return 1;
    }
    
    // 设置SSL上下文
    evhttp_set_ssl_context(http, ssl_ctx);
    
    // 绑定到端口
    if (evhttp_bind_socket(http, "0.0.0.0", PORT) != 0) {
        fprintf(stderr, "Failed to bind to port %d\n", PORT);
        evhttp_free(http);
        event_base_free(base);
        SSL_CTX_free(ssl_ctx);
        return 1;
    }
    
    // 设置请求处理回调
    evhttp_set_gencb(http, https_request_handler, NULL);
    
    printf("HTTPS Server running on https://localhost:%d\n", PORT);
    printf("Press Ctrl+C to stop\n");
    
    // 进入事件循环
    event_base_dispatch(base);
    
    // 清理资源
    evhttp_free(http);
    event_base_free(base);
    SSL_CTX_free(ssl_ctx);
    
    return 0;
}

生成自签名证书(测试用):

# 生成私钥
openssl genrsa -out server.key 2048

# 生成证书签名请求
openssl req -new -key server.key -out server.csr

# 生成自签名证书
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

# 清理CSR文件
rm server.csr

9. 性能优化

9.1 连接池管理

示例代码:connection_pool.c

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

// 数据库连接结构体
typedef struct {
    sqlite3 *db;
    bool in_use;
    time_t last_used;
} db_connection_t;

// 连接池
typedef struct {
    db_connection_t *connections;
    int size;
    int max_size;
    pthread_mutex_t lock;
    pthread_cond_t cond;
} connection_pool_t;

// 初始化连接池
connection_pool_t* connection_pool_init(int max_size) {
    connection_pool_t *pool = malloc(sizeof(connection_pool_t));
    pool->max_size = max_size;
    pool->size = 0;
    pool->connections = malloc(sizeof(db_connection_t) * max_size);
    
    pthread_mutex_init(&pool->lock, NULL);
    pthread_cond_init(&pool->cond, NULL);
    
    return pool;
}

// 获取连接
db_connection_t* connection_pool_get(connection_pool_t *pool) {
    pthread_mutex_lock(&pool->lock);
    
    // 查找可用连接
    for (int i = 0; i < pool->size; i++) {
        if (!pool->connections[i].in_use) {
            pool->connections[i].in_use = true;
            pool->connections[i].last_used = time(NULL);
            pthread_mutex_unlock(&pool->lock);
            return &pool->connections[i];
        }
    }
    
    // 如果没有可用连接且未达到最大值,创建新连接
    if (pool->size < pool->max_size) {
        db_connection_t *conn = &pool->connections[pool->size];
        sqlite3 *db;
        
        if (sqlite3_open("webservice.db", &db) == SQLITE_OK) {
            conn->db = db;
            conn->in_use = true;
            conn->last_used = time(NULL);
            pool->size++;
            pthread_mutex_unlock(&pool->lock);
            return conn;
        }
    }
    
    // 等待可用连接
    while (pool->size >= pool->max_size) {
        pthread_cond_wait(&pool->cond, &pool->lock);
    }
    
    pthread_mutex_unlock(&pool->lock);
    return connection_pool_get(pool); // 递归调用
}

// 释放连接
void connection_pool_release(connection_pool_t *pool, db_connection_t *conn) {
    pthread_mutex_lock(&pool->lock);
    conn->in_use = false;
    pthread_cond_signal(&pool->cond);
    pthread_mutex_unlock(&pool->lock);
}

// 销毁连接池
void connection_pool_free(connection_pool_t *pool) {
    pthread_mutex_lock(&pool->lock);
    
    for (int i = 0; i < pool->size; i++) {
        if (pool->connections[i].db) {
            sqlite3_close(pool->connections[i].db);
        }
    }
    
    free(pool->connections);
    pthread_mutex_unlock(&pool->lock);
    pthread_mutex_destroy(&pool->lock);
    pthread_cond_destroy(&pool->cond);
    free(pool);
}

9.2 缓存机制

示例代码:cache.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>

// 缓存条目
typedef struct {
    char *key;
    char *value;
    time_t expires_at;
    bool valid;
} cache_entry_t;

// 缓存结构
typedef struct {
    cache_entry_t *entries;
    int size;
    int capacity;
    pthread_mutex_t lock;
} cache_t;

// 初始化缓存
cache_t* cache_init(int capacity) {
    cache_t *cache = malloc(sizeof(cache_t));
    cache->capacity = capacity;
    cache->size = 0;
    cache->entries = malloc(sizeof(cache_entry_t) * capacity);
    
    pthread_mutex_init(&cache->lock, NULL);
    
    // 初始化所有条目
    for (int i = 0; i < capacity; i++) {
        cache->entries[i].valid = false;
    }
    
    return cache;
}

// 哈希函数(简单版本)
unsigned int hash_key(const char *key) {
    unsigned int hash = 5381;
    int c;
    
    while ((c = *key++)) {
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }
    
    return hash;
}

// 设置缓存
void cache_set(cache_t *cache, const char *key, const char *value, int ttl_seconds) {
    pthread_mutex_lock(&cache->lock);
    
    unsigned int hash = hash_key(key) % cache->capacity;
    int index = hash;
    
    // 查找空位或相同key
    for (int i = 0; i < cache->capacity; i++) {
        int current_index = (index + i) % cache->capacity;
        
        if (!cache->entries[current_index].valid || 
            strcmp(cache->entries[current_index].key, key) == 0) {
            
            // 释放旧值
            if (cache->entries[current_index].valid) {
                free(cache->entries[current_index].key);
                free(cache->entries[current_index].value);
            }
            
            // 设置新值
            cache->entries[current_index].key = strdup(key);
            cache->entries[current_index].value = strdup(value);
            cache->entries[current_index].expires_at = time(NULL) + ttl_seconds;
            cache->entries[current_index].valid = true;
            
            if (cache->entries[current_index].valid) {
                cache->size++;
            }
            
            break;
        }
    }
    
    pthread_mutex_unlock(&cache->lock);
}

// 获取缓存
char* cache_get(cache_t *cache, const char *key) {
    pthread_mutex_lock(&cache->lock);
    
    unsigned int hash = hash_key(key) % cache->capacity;
    int index = hash;
    
    for (int i = 0; i < cache->capacity; i++) {
        int current_index = (index + i) % cache->capacity;
        
        if (cache->entries[current_index].valid && 
            strcmp(cache->entries[current_index].key, key) == 0) {
            
            // 检查是否过期
            if (time(NULL) > cache->entries[current_index].expires_at) {
                cache->entries[current_index].valid = false;
                free(cache->entries[current_index].key);
                free(cache->entries[current_index].value);
                cache->size--;
                pthread_mutex_unlock(&cache->lock);
                return NULL;
            }
            
            char *result = strdup(cache->entries[current_index].value);
            pthread_mutex_unlock(&cache->lock);
            return result;
        }
    }
    
    pthread_mutex_unlock(&cache->lock);
    return NULL;
}

// 清理过期缓存
void cache_cleanup(cache_t *cache) {
    pthread_mutex_lock(&cache->lock);
    
    for (int i = 0; i < cache->capacity; i++) {
        if (cache->entries[i].valid && 
            time(NULL) > cache->entries[i].expires_at) {
            cache->entries[i].valid = false;
            free(cache->entries[i].key);
            free(cache->entries[i].value);
            cache->size--;
        }
    }
    
    pthread_mutex_unlock(&cache->lock);
}

// 销毁缓存
void cache_free(cache_t *cache) {
    pthread_mutex_lock(&cache->lock);
    
    for (int i = 0; i < cache->capacity; i++) {
        if (cache->entries[i].valid) {
            free(cache->entries[i].key);
            free(cache->entries[i].value);
        }
    }
    
    free(cache->entries);
    pthread_mutex_unlock(&cache->lock);
    pthread_mutex_destroy(&cache->lock);
    free(cache);
}

10. 日志系统

10.1 日志级别与格式

示例代码:logger.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>

// 日志级别
typedef enum {
    LOG_DEBUG = 0,
    LOG_INFO = 1,
    LOG_WARN = 2,
    LOG_ERROR = 3,
    LOG_FATAL = 4
} log_level_t;

// 日志配置
typedef struct {
    FILE *file;
    log_level_t level;
    bool use_color;
    pthread_mutex_t lock;
} logger_t;

// 日志级别名称
const char* level_names[] = {
    "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};

// 日志级别颜色(ANSI)
const char* level_colors[] = {
    "\033[36m", // DEBUG - 青色
    "\033[32m", // INFO - 绿色
    "\033[33m", // WARN - 黄色
    "\033[31m", // ERROR - 红色
    "\033[35m"  // FATAL - 紫色
};

const char* reset_color = "\033[0m";

// 初始化日志器
logger_t* logger_init(const char *filename, log_level_t level, bool use_color) {
    logger_t *logger = malloc(sizeof(logger_t));
    
    if (filename) {
        logger->file = fopen(filename, "a");
        if (!logger->file) {
            fprintf(stderr, "Failed to open log file: %s\n", filename);
            free(logger);
            return NULL;
        }
    } else {
        logger->file = stdout;
    }
    
    logger->level = level;
    logger->use_color = use_color;
    pthread_mutex_init(&logger->lock, NULL);
    
    return logger;
}

// 获取当前时间字符串
void get_timestamp(char *buffer, size_t size) {
    time_t now = time(NULL);
    struct tm *tm_info = localtime(&now);
    strftime(buffer, size, "%Y-%m-%d %H:%M:%S", tm_info);
}

// 记录日志
void logger_log(logger_t *logger, log_level_t level, 
                const char *file, int line, const char *format, ...) {
    if (level < logger->level) {
        return;
    }
    
    pthread_mutex_lock(&logger->lock);
    
    char timestamp[20];
    get_timestamp(timestamp, sizeof(timestamp));
    
    // 格式化消息
    va_list args;
    va_start(args, format);
    char message[1024];
    vsnprintf(message, sizeof(message), format, args);
    va_end(args);
    
    // 输出到文件
    if (logger->use_color && logger->file == stdout) {
        fprintf(logger->file, "%s[%s] %s:%d %s: %s%s\n",
                level_colors[level],
                timestamp,
                file,
                line,
                level_names[level],
                message,
                reset_color);
    } else {
        fprintf(logger->file, "[%s] %s:%d %s: %s\n",
                timestamp,
                file,
                line,
                level_names[level],
                message);
    }
    
    fflush(logger->file);
    pthread_mutex_unlock(&logger->lock);
}

// 便捷宏定义
#define LOG_DEBUG(logger, ...) logger_log(logger, LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_INFO(logger, ...) logger_log(logger, LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_WARN(logger, ...) logger_log(logger, LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_ERROR(logger, ...) logger_log(logger, LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_FATAL(logger, ...) logger_log(logger, LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)

// 销毁日志器
void logger_free(logger_t *logger) {
    if (logger->file && logger->file != stdout) {
        fclose(logger->file);
    }
    pthread_mutex_destroy(&logger->lock);
    free(logger);
}

11. 测试与部署

11.1 单元测试

示例代码:test.c

#include <stdio.h>
#include <assert.h>
#include <string.h>

// 测试URL解析
void test_url_parser() {
    printf("Testing URL parser...\n");
    
    query_params_t *params = parse_query_string("page=1&limit=10&sort=name");
    
    assert(params != NULL);
    assert(params->count == 3);
    
    assert(strcmp(query_params_get(params, "page"), "1") == 0);
    assert(strcmp(query_params_get(params, "limit"), "10") == 0);
    assert(strcmp(query_params_get(params, "sort"), "name") == 0);
    
    query_params_free(params);
    printf("URL parser tests passed!\n");
}

// 测试JSON处理
void test_json_handler() {
    printf("Testing JSON handler...\n");
    
    user_t user = {1, "Test User", "test@example.com"};
    char *json_str = user_to_json(&user);
    
    assert(json_str != NULL);
    assert(strstr(json_str, "\"id\":1") != NULL);
    assert(strstr(json_str, "\"name\":\"Test User\"") != NULL);
    
    user_t *parsed = json_to_user(json_str);
    assert(parsed != NULL);
    assert(parsed->id == 1);
    assert(strcmp(parsed->name, "Test User") == 0);
    
    free(parsed->name);
    free(parsed->email);
    free(parsed);
    free(json_str);
    
    printf("JSON handler tests passed!\n");
}

// 测试输入验证
void test_input_validation() {
    printf("Testing input validation...\n");
    
    assert(validate_email("test@example.com") == true);
    assert(validate_email("invalid") == false);
    assert(validate_email("") == false);
    assert(validate_email(NULL) == false);
    
    char *escaped = escape_sql_string("O'Brien");
    assert(strcmp(escaped, "O\\'Brien") == 0);
    free(escaped);
    
    printf("Input validation tests passed!\n");
}

int main() {
    printf("Running tests...\n\n");
    
    test_url_parser();
    test_json_handler();
    test_input_validation();
    
    printf("\nAll tests passed!\n");
    return 0;
}

11.2 部署脚本

示例代码:deploy.sh

#!/bin/bash

# 部署脚本
set -e

echo "开始部署C WebService..."

# 1. 更新系统
echo "1. 更新系统包..."
sudo apt-get update
sudo apt-get upgrade -y

# 2. 安装依赖
echo "2. 安装依赖..."
sudo apt-get install -y build-essential libmicrohttpd-dev libevent-dev \
    libcurl4-openssl-dev libssl-dev libcjson-dev sqlite3 libsqlite3-dev

# 3. 编译项目
echo "3. 编译项目..."
make clean
make

# 4. 创建系统服务
echo "4. 创建系统服务..."
sudo tee /etc/systemd/system/c-webservice.service > /dev/null <<EOF
[Unit]
Description=C WebService
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/c-webservice
ExecStart=/opt/c-webservice/bin/webservice
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

# 5. 创建目录
echo "5. 创建目录..."
sudo mkdir -p /opt/c-webservice/bin
sudo mkdir -p /opt/c-webservice/logs
sudo mkdir -p /opt/c-webservice/data

# 6. 复制文件
echo "6. 复制文件..."
sudo cp webservice /opt/c-webservice/bin/
sudo cp -r config /opt/c-webservice/
sudo chown -R www-data:www-data /opt/c-webservice

# 7. 启用服务
echo "7. 启用服务..."
sudo systemctl daemon-reload
sudo systemctl enable c-webservice
sudo systemctl start c-webservice

# 8. 检查状态
echo "8. 检查服务状态..."
sudo systemctl status c-webservice

echo "部署完成!"
echo "服务日志: journalctl -u c-webservice -f"

12. 完整项目示例

12.1 项目结构

c-webservice/
├── src/
│   ├── main.c
│   ├── server.c
│   ├── router.c
│   ├── request.c
│   ├── response.c
│   ├── database.c
│   ├── cache.c
│   ├── logger.c
│   └── utils.c
├── include/
│   ├── server.h
│   ├── router.h
│   ├── request.h
│   ├── response.h
│   ├── database.h
│   ├── cache.h
│   ├── logger.h
│   └── utils.h
├── tests/
│   ├── test_server.c
│   ├── test_router.c
│   └── test_database.c
├── config/
│   ├── config.json
│   └── logging.conf
├── docs/
│   ├── API.md
│   └── ARCHITECTURE.md
├── Makefile
├── CMakeLists.txt
├── README.md
└── LICENSE

12.2 Makefile示例

# Makefile for C WebService

CC = gcc
CFLAGS = -Wall -Wextra -std=c99 -O2
LDFLAGS = -levent -lmicrohttpd -lcjson -lsqlite3 -lpthread -lssl -lcrypto

# 源文件
SRC_DIR = src
INC_DIR = include
TEST_DIR = tests

SOURCES = $(wildcard $(SRC_DIR)/*.c)
OBJECTS = $(SOURCES:.c=.o)
TARGET = webservice

TEST_SOURCES = $(wildcard $(TEST_DIR)/*.c)
TEST_OBJECTS = $(TEST_SOURCES:.c=.o)
TEST_TARGET = test_webservice

# 默认目标
all: $(TARGET)

# 编译主程序
$(TARGET): $(OBJECTS)
	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)

# 编译测试程序
test: $(TEST_OBJECTS) $(filter-out $(SRC_DIR)/main.o, $(OBJECTS))
	$(CC) $(CFLAGS) -o $(TEST_TARGET) $^ $(LDFLAGS)

# 编译单个源文件
%.o: %.c
	$(CC) $(CFLAGS) -I$(INC_DIR) -c $< -o $@

# 清理
clean:
	rm -f $(OBJECTS) $(TEST_OBJECTS) $(TARGET) $(TEST_TARGET)

# 安装
install: $(TARGET)
	sudo cp $(TARGET) /usr/local/bin/
	sudo chmod +x /usr/local/bin/$(TARGET)

# 卸载
uninstall:
	sudo rm -f /usr/local/bin/$(TARGET)

# 运行测试
run_tests: test
	./$(TEST_TARGET)

# 格式化代码
format:
	find . -name "*.c" -o -name "*.h" | xargs clang-format -i

# 代码检查
lint:
	splint -weak $(SOURCES)

.PHONY: all clean install uninstall run_tests format lint

13. 性能监控与调优

13.1 性能指标收集

示例代码:metrics.c

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

// 性能指标结构体
typedef struct {
    long long total_requests;
    long long successful_requests;
    long long failed_requests;
    double total_response_time; // 总响应时间(秒)
    double max_response_time;
    double min_response_time;
    pthread_mutex_t lock;
} metrics_t;

// 初始化指标
metrics_t* metrics_init() {
    metrics_t *metrics = malloc(sizeof(metrics_t));
    metrics->total_requests = 0;
    metrics->successful_requests = 0;
    metrics->failed_requests = 0;
    metrics->total_response_time = 0.0;
    metrics->max_response_time = 0.0;
    metrics->min_response_time = 0.0;
    pthread_mutex_init(&metrics->lock, NULL);
    return metrics;
}

// 记录请求
void metrics_record_request(metrics_t *metrics, bool success, double response_time) {
    pthread_mutex_lock(&metrics->lock);
    
    metrics->total_requests++;
    
    if (success) {
        metrics->successful_requests++;
    } else {
        metrics->failed_requests++;
    }
    
    metrics->total_response_time += response_time;
    
    if (response_time > metrics->max_response_time) {
        metrics->max_response_time = response_time;
    }
    
    if (metrics->min_response_time == 0.0 || response_time < metrics->min_response_time) {
        metrics->min_response_time = response_time;
    }
    
    pthread_mutex_unlock(&metrics->lock);
}

// 打印指标
void metrics_print(metrics_t *metrics) {
    pthread_mutex_lock(&metrics->lock);
    
    printf("\n=== Performance Metrics ===\n");
    printf("Total Requests: %lld\n", metrics->total_requests);
    printf("Successful Requests: %lld\n", metrics->successful_requests);
    printf("Failed Requests: %lld\n", metrics->failed_requests);
    
    if (metrics->total_requests > 0) {
        printf("Success Rate: %.2f%%\n", 
               (double)metrics->successful_requests / metrics->total_requests * 100);
        printf("Average Response Time: %.3f ms\n", 
               (metrics->total_response_time / metrics->total_requests) * 1000);
    }
    
    printf("Max Response Time: %.3f ms\n", metrics->max_response_time * 1000);
    printf("Min Response Time: %.3f ms\n", metrics->min_response_time * 1000);
    printf("===========================\n\n");
    
    pthread_mutex_unlock(&metrics->lock);
}

// 销毁指标
void metrics_free(metrics_t *metrics) {
    pthread_mutex_destroy(&metrics->lock);
    free(metrics);
}

14. 总结

通过本文的详细指导,你已经学习了如何使用C语言从零开始构建一个高效、稳定的Web服务系统。我们涵盖了以下关键方面:

  1. 环境搭建:选择合适的开发工具和库
  2. HTTP协议基础:理解请求和响应结构
  3. 服务器实现:使用libmicrohttpd和libevent创建服务器
  4. 路由系统:设计灵活的路由机制
  5. 请求处理:解析URL参数和路径参数
  6. JSON处理:使用cJSON库进行数据序列化
  7. 数据库集成:使用SQLite进行数据持久化
  8. 安全性:输入验证、SQL注入防护、HTTPS支持
  9. 性能优化:连接池、缓存机制
  10. 日志系统:结构化日志记录
  11. 测试与部署:单元测试和部署脚本
  12. 完整项目:项目结构和构建配置
  13. 性能监控:指标收集和分析

进一步学习建议

  1. 深入学习网络编程:研究TCP/IP协议栈、Socket编程
  2. 性能调优:学习更多优化技术,如零拷贝、内存池
  3. 并发模型:深入研究多线程、协程、异步I/O
  4. 安全实践:学习更多安全漏洞和防护措施
  5. 生产环境部署:学习容器化(Docker)、负载均衡、监控告警

资源推荐

  • 书籍:《Unix网络编程》、《C陷阱与缺陷》
  • 在线资源:libevent官方文档、OpenSSL文档、SQLite文档
  • 开源项目:Nginx(C语言实现的高性能Web服务器)、Redis(C语言实现的内存数据库)

通过不断实践和优化,你可以构建出媲美商业级产品的Web服务系统。记住,性能、稳定性和安全性是Web服务的三大支柱,需要在开发过程中持续关注和改进。