目录
一、简介
CivetWeb是一个开源的、轻量级且高效的HTTP服务器和嵌入式Web框架。以下是对CivetWeb的详细介绍:
1. 基本概述
- 项目起源:CivetWeb最初基于Mongoose项目,但在2013年由于许可证变更,CivetWeb从Mongoose分叉出来,成为一个独立的项目。
- 开发目标:CivetWeb旨在创建一个易于集成到其他应用程序中的小型Web服务器,适合在资源受限的环境中(如IoT设备和嵌入式系统)运行。
2. 技术特性
- 跨平台支持:CivetWeb采用C语言编写,因此可以在多种操作系统上运行,包括Windows、Linux、FreeBSD、Mac OS X等。
- 模块化设计:CivetWeb具有模块化架构,容易扩展,可以通过插件或自定义处理函数添加新的功能。
- 高效稳定:CivetWeb使用异步模型处理请求,支持事件驱动的非阻塞I/O,有效利用系统资源,提高并发性能。同时,它支持多线程模式,可以在需要时提供更高的并行处理能力。
- 安全性:CivetWeb内置对SSL/TLS的支持,确保数据传输的安全性。
- 灵活性:CivetWeb支持HTTP/1.1标准协议,并内建WebSocket功能,方便实现双向实时通信。同时,它提供了简单的API,开发者可以通过回调函数处理HTTP请求和响应,支持基于CGI、Lua脚本或自定义处理器生成动态网页内容。
二、CivetHandler类
(一)HTTP的request种类:
-
GET:请求指定的页面信息,并返回实体主体。这是最常用的HTTP方法,用于请求服务器发送资源。GET方法应该只被用于请求数据(即不应当产生副作用,如更改数据)。
-
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。POST请求可能会导致新的资源的建立和/或已有资源的修改。
-
PUT:从客户端向服务器传送的数据取代指定的文档的内容。PUT方法要求请求报文的主体中包含被上传的资源,然后URL指向了那个资源的存放位置。
-
DELETE:请求服务器删除指定的页面。DELETE请求用于请求服务器删除指定的资源。
-
CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。
-
OPTIONS:允许客户端查看服务器的性能。这个方法会返回服务器针对特定资源所支持的HTTP请求方法,或者用来检查服务器的性能。
-
TRACE:回显服务器收到的请求,主要用于测试或诊断。
-
PATCH:是对PUT方法的补充,用来对已知资源进行局部更新。PUT方法是用新文档内容替换目标资源的全部内容,而PATCH方法则是对目标资源部分内容进行更新。
-
HEAD:类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头。
(二)CivetHandler类请求处理句柄
形如handleGet,CivetHandler对GET、POST、PUT、DELETE、OPTIONS、PATCH、HEAD都有对应的请求处理回调,选择需要的回调函数重写具体实现。
三、函数用法
1. mg_get_var
含义:这个函数用于从 HTTP 请求中提取查询字符串参数(如表单提交的数据)。
用法:
const char* data;
int data_len = mg_get_var(conn, "variable_name", &data);
if (data_len > 0) {
// 使用 data
}
mg_free((void*)data); // 释放分配的内存
2. mg_printf
含义:用于向连接发送格式化的输出,类似于标准 C 中的 printf
函数。
用法:
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
mg_printf(conn, "<html><body>%s</body></html>", "Hello, world!");
3. mg_get_request_info
含义:获取当前 HTTP 请求的详细信息,如请求方法、URI 和查询字符串等。
用法:
struct mg_request_info *request_info = mg_get_request_info(conn);
printf("Requested URI: %s\n", request_info->request_uri);
4. mg_get_header
含义:从 HTTP 请求中获取指定的头部字段的值。
用法:
const char* user_agent = mg_get_header(conn, "User-Agent");
if (user_agent) {
printf("User-Agent: %s\n", user_agent);
}
5. mg_send_http_redirect
含义:发送 HTTP 重定向响应到客户端。
用法:
mg_send_http_redirect(conn, "http://example.com/new_location", 302);
6. mg_read
含义:从 HTTP 请求的正文中读取数据,用于处理 POST 请求。
用法:
char post_data[1024];
int read_length = mg_read(conn, post_data, sizeof(post_data));
if (read_length > 0) {
// 处理 post_data
}
7. mg_md5
含义:生成给定字符串的 MD5 散列。通常用于密码或数据的哈希处理。
用法:
char hash[33];
mg_md5(hash, "data_to_hash", NULL);
printf("MD5 Hash: %s\n", hash);
四、Demo
#include "civetweb.h"
#include <stdio.h>
// 定义一个处理HTTP GET请求的函数
int request_handler(struct mg_connection *conn, void *cbdata) {
const struct mg_request_info *req_info = mg_get_request_info(conn);
if (req_info->local_uri == NULL || req_info->local_uri[0] == '\0') {
// 如果请求的是根URL(/)
mg_printf(conn,
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n"
"<html><body><h1>Hello, CivetWeb!</h1></body></html>");
} else {
// 对于其他URL,返回404
mg_printf(conn,
"HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/plain\r\n"
"Connection: close\r\n\r\n"
"404 Not Found");
}
return 200; // 返回HTTP状态码(虽然这里返回的值对CivetWeb没有直接影响)
}
int main(void) {
struct mg_context *ctx;
const char *options[] = {
"listening_ports", "8080",
"document_root", ".", // 设置文档根目录为当前目录
"enable_directory_listing", "yes",
NULL
};
// 初始化服务器
ctx = mg_start(NULL, 0, options, request_handler, NULL);
if (ctx == NULL) {
fprintf(stderr, "Failed to start CivetWeb\n");
return 1;
}
// 等待直到服务器被关闭(在这个例子中,我们将无限期地等待,直到用户手动停止程序)
printf("CivetWeb server started on port 8080. Press Ctrl+C to stop.\n");
getchar(); // 等待用户输入,以便观察输出
// 停止服务器
mg_stop(ctx);
return 0;
}