libmicrohttpd 入门

libmicrohttpd 是一个小型的 C 库,用于在项目中嵌入 HTTP 服务器功能。它设计简单、轻量级,适合需要 HTTP 接口但不想要大型 Web 服务器开销的应用程序。

安装 libmicrohttpd

Linux 系统

在基于 Debian/Ubuntu 的系统上:

bash

sudo apt-get install libmicrohttpd-dev

在基于 RHEL/CentOS 的系统上:

bash

sudo yum install libmicrohttpd-devel

macOS 系统

bash

brew install libmicrohttpd

从源码编译

  1. 下载源码:https://ftp.gnu.org/gnu/libmicrohttpd/

  2. 解压并进入目录

  3. 编译安装:

bash

./configure
make
sudo make install

基本使用示例

最简单的 HTTP 服务器

c

#include <microhttpd.h>
#include <stdio.h>
#include <string.h>#define PORT 8888static enum MHD_Result answer_to_connection(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)
{const char *page = "<html><body>Hello, browser!</body></html>";struct MHD_Response *response;enum MHD_Result ret;response = MHD_create_response_from_buffer(strlen(page),(void*)page, MHD_RESPMEM_PERSISTENT);ret = MHD_queue_response(connection, MHD_HTTP_OK, response);MHD_destroy_response(response);return ret;
}int main()
{struct MHD_Daemon *daemon;daemon = MHD_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, PORT,NULL, NULL, &answer_to_connection, NULL,MHD_OPTION_END);if (NULL == daemon) {return 1;}getchar();MHD_stop_daemon(daemon);return 0;
}

编译并运行:

bash

gcc simple_server.c -o server -lmicrohttpd
./server

然后访问 http://localhost:8888

主要功能特性

  1. 支持 HTTP 1.1

  2. 多种线程模型

    • 单线程

    • 多线程(线程池)

    • 每个连接一个线程

  3. 支持 HTTPS(需要 GnuTLS 或类似库)

  4. IPv6 支持

  5. 基本认证和摘要认证

  6. 可处理 POST 数据

  7. 非阻塞模式

处理 POST 请求示例

c

#include <microhttpd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define PORT 8888struct connection_info {char *data;size_t size;
};static enum MHD_Result post_iterator(void *cls, enum MHD_ValueKind kind,const char *key, const char *filename,const char *content_type,const char *transfer_encoding,const char *data, uint64_t off,size_t size)
{struct connection_info *con_info = cls;if (0 == size) return MHD_YES;if (NULL == con_info->data) {con_info->data = malloc(size + 1);if (NULL == con_info->data) return MHD_NO;con_info->size = size;memcpy(con_info->data, data, size);con_info->data[size] = '\0';} else {char *new_data = realloc(con_info->data, con_info->size + size + 1);if (NULL == new_data) return MHD_NO;con_info->data = new_data;memcpy(con_info->data + con_info->size, data, size);con_info->size += size;con_info->data[con_info->size] = '\0';}return MHD_YES;
}static void request_completed(void *cls, struct MHD_Connection *connection,void **con_cls, enum MHD_RequestTerminationCode toe)
{struct connection_info *con_info = *con_cls;if (NULL == con_info) return;if (NULL != con_info->data) free(con_info->data);free(con_info);*con_cls = NULL;
}static enum MHD_Result answer_to_connection(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)
{if (NULL == *con_cls) {struct connection_info *con_info;con_info = malloc(sizeof(struct connection_info));if (NULL == con_info) return MHD_NO;con_info->data = NULL;con_info->size = 0;*con_cls = con_info;return MHD_YES;}if (0 != strcmp(method, "POST")) {const char *page = "<html><body>This server only accepts POST requests</body></html>";struct MHD_Response *response;enum MHD_Result ret;response = MHD_create_response_from_buffer(strlen(page),(void*)page, MHD_RESPMEM_PERSISTENT);ret = MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, response);MHD_destroy_response(response);return ret;}if (*upload_data_size != 0) {struct connection_info *con_info = *con_cls;MHD_post_process(con_info->post_processor, upload_data, *upload_data_size);*upload_data_size = 0;return MHD_YES;} else {struct connection_info *con_info = *con_cls;const char *page;struct MHD_Response *response;enum MHD_Result ret;if (NULL == con_info->data) {page = "<html><body>No data received</body></html>";} else {char *reply = malloc(100 + con_info->size);sprintf(reply, "<html><body>You posted: %s</body></html>", con_info->data);page = reply;}response = MHD_create_response_from_buffer(strlen(page),(void*)page, MHD_RESPMEM_MUST_FREE);ret = MHD_queue_response(connection, MHD_HTTP_OK, response);MHD_destroy_response(response);return ret;}
}int main()
{struct MHD_Daemon *daemon;daemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, PORT,NULL, NULL, &answer_to_connection, NULL,MHD_OPTION_NOTIFY_COMPLETED, &request_completed, NULL,MHD_OPTION_END);if (NULL == daemon) {return 1;}getchar();MHD_stop_daemon(daemon);return 0;
}

进阶主题

  1. HTTPS 支持

    • 需要链接 GnuTLS 库

    • 使用 MHD_USE_SSL 标志

    • 提供证书和密钥文件

  2. 多线程模式

    • MHD_USE_THREAD_PER_CONNECTION - 每个连接一个线程

    • MHD_USE_INTERNAL_POLLING_THREAD - 内部轮询线程

    • MHD_USE_SELECT_INTERNALLY - 使用 select() 进行内部轮询

  3. 性能优化

    • 使用连接池

    • 合理设置线程数

    • 启用 TCP 快速打开

资源

  1. 官方文档

  2. API 参考手册

  3. GitHub 仓库

这个入门指南涵盖了 libmicrohttpd 的基本用法。根据你的需求,可以进一步探索更高级的功能如 WebSocket 支持、HTTP/2 等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93880.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络】使用 DNAT 进行负载均衡时,若未配置配套的 SNAT,回包失败

【网络】iptables 1 概念 【网络】iptables 2 查看规则 【网络】使用 DNAT 进行负载均衡时&#xff0c;若未配置配套的 SNAT&#xff0c;回包失败 【网络】回包路由原理 使用 DNAT 进行负载均衡时&#xff0c;若未配置配套的 SNAT&#xff0c;后端服务器将直接回包给客户端&am…

深入解析GCC:从编译原理到嵌入式底层实战

继续更新编译器底层系列&#xff01;&#xff01;&#xff01;硬核C语言的屠龙之术&#xff1a;从GCC到汇编的底层征途&#xff08;一&#xff09;总纲&#xff1a; 恭喜你&#xff0c;决定踏上这条通往嵌入式大佬的硬核之路。这条路的起点&#xff0c;不是C语言的语法书&#…

最新MySQL面试题(2025超详细版)

2025最新超详细MySQL面试题 文章目录2025最新超详细MySQL面试题[toc]一、 SQL 和基本操作1. SQL的执行顺序2. 如何优化MySQL查询3. 常用的聚合函数4. 数据库事务5. 事务的四大特性(ACID)6. 视图7. MySQL中使用LIMIT子句进行分页8. MySQL中使用变量和用户定义的函数9. MySQL中的…

Spring Retry实战指南_让你的应用更具韧性

1 Spring Retry概述 1.1 什么是Spring Retry Spring Retry是Spring生态系统中的一个重要组件,专门用于处理应用程序中的重试逻辑。在分布式系统和微服务架构中,网络通信、外部服务调用、数据库访问等操作都可能因为各种原因而失败,如网络抖动、服务暂时不可用、资源竞争等…

大数据毕业设计选题推荐-基于大数据的1688商品类目关系分析与可视化系统-Hadoop-Spark-数据可视化-BigData

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇…

【Grafana】grafana-image-renderer配合python脚本实现仪表盘导出pdf

背景 os&#xff1a;centos7Grafana&#xff1a;v12grafana-image-renderer&#xff1a;v4.0.10插件&#xff1a;否grafana-image-renderer可以以插件形式启动&#xff0c;也可以以单独服务启动&#xff0c;在centos7插件启动时&#xff0c;报错glibc版本太低&#xff0c;未找到…

静/动态库 IIC(arm) day58

十七&#xff1a;动态库和静态库 库&#xff1a;一堆可执行二进制文件的集合&#xff0c;由若干个.o文件归并生成 一&#xff1a;静态(链接)库&#xff1a;libxxx.a 生成一个独立的可执行程序(运行时仅需要一个文件即可) 使用方便 不需要安装 文件比较大 多个程序使用同一个静态…

uniapp 手写签名组件开发全攻略

引言在移动应用开发中&#xff0c;手写签名功能是一个常见的需求&#xff0c;特别是在电子合同、审批流程、金融交易等场景中。本文将详细介绍如何基于uni-app框架开发一个高性能、功能丰富的手写签名组件&#xff0c;并分享开发过程中的技术要点和最佳实践。组件概述这个签名组…

理解JavaScript中的函数赋值和调用

&#x1f468; 作者简介&#xff1a;大家好&#xff0c;我是Taro&#xff0c;全栈领域创作者 ✒️ 个人主页&#xff1a;唐璜Taro &#x1f680; 支持我&#xff1a;点赞&#x1f44d;&#x1f4dd; 评论 ⭐️收藏 文章目录前言一、函数赋值二、函数调用三、 代码示例总结前言…

交叉编译 手动安装 SQLite 库 移植ARM

# 下载源码 wget https://www.sqlite.org/2023/sqlite-autoconf-3420000.tar.gz tar -xzf sqlite-autoconf-3420000.tar.gz cd sqlite-autoconf-3420000cd /home/lxh/sqlite-autoconf-3420000 make distclean //清除下&#xff0c;因为我安装失败过。 ./configure --hostarm-…

翻译记忆库(TMX)与机器翻译的结合应用

更多内容请见: 机器翻译修炼-专栏介绍和目录 文章目录 一、核心概念解析 1.1 翻译记忆库 (Translation Memory, TM) 1.2 翻译记忆交换格式 (Translation Memory eXchange, TMX) 二、为何要将两者结合? 2.1 TM和MT的优势是高度互补的 2.2 TMX在结合中的关键作用 2.3 TMX与MT的…

SpringBoot中集成eclipse.paho.client.mqttv3实现mqtt客户端并支持断线重连、线程池高并发改造、存储入库mqsql和redis示例业务流程,附资源下载

场景 SpringBoot整合MQTT服务器实现消息的发送与订阅(推送消息与接收推送)&#xff1a; SpringBoot整合MQTT服务器实现消息的发送与订阅(推送消息与接收推送)_服务端接收mqtt消息-CSDN博客 上面SpringBoot集成MQTT使用的是spring-integration-mqtt依赖&#xff0c;也是经常使…

【考研408数据结构-08】 图论基础:存储结构与遍历算法

&#x1f4da; 【考研408数据结构-08】 图论基础&#xff1a;存储结构与遍历算法 &#x1f3af; 考频&#xff1a;⭐⭐⭐⭐⭐ | 题型&#xff1a;选择题、综合应用题、算法设计题 | 分值&#xff1a;约8-15分 引言 想象你正在规划一次跨省自驾游&#xff0c;面前摊开一张复杂的…

SQL查询语句的执行顺序

好的&#xff0c;我们来详细讲解一下 SQL 查询语句的执行顺序。 很多人会误以为 SQL 的执行顺序就是我们写的顺序&#xff08;SELECT -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY&#xff09;&#xff0c;但实际上&#xff0c;数据库引擎在底层处理查询…

【Android】OKHttp网络请求原理和弱网优化

【Android】OKHttp网络请求原理和弱网优化 1. OkHttp 网络请求原理 OkHttp 的请求过程可以分为 四个关键阶段&#xff1a; &#xff08;假设你是通过 OkHttpClient.newCall(request).enqueue(callback) 发的请求&#xff09; OkHttpClient│▼ Dispatcher (调度器)│▼ RealC…

概率论基础教程第4章 随机变量(四)

4.7 泊松随机变量 定义 泊松随机变量&#xff1a;如果一个取值于 $ 0, 1, 2, \ldots $ 的随机变量对某一个 $ \lambda > 0 $&#xff0c;其分布列为&#xff1a; p(i)P{Xi}e−λλii!i0,1,2,⋯(7.1) \boxed{p(i) P\{X i\} e^{-\lambda} \frac{\lambda^i}{i!} \qquad i 0…

Unity高级开发:反射原理深入解析与实践指南 C#

Unity高级开发&#xff1a;反射原理深入解析与实践指南 在Unity游戏开发中&#xff0c;反射&#xff08;Reflection&#xff09; 是一项强大的元编程技术&#xff0c;它允许程序在运行时动态地获取类型信息、创建对象和调用方法。根据Unity官方统计&#xff0c;超过78%的商业游…

任务五 推荐页面功能开发

一、推荐页面需求分析 由推荐页面效果图,可以看出,推荐页面主要由顶部轮播图和歌单列表页面组成 二、推荐页面轮播图组件封装 由于轮播图,可能在项目多个地方用到,因此可以将轮播图抽调成一个组件,然后各个页面调用这个组件。 在开发轮播图组件时,需要安装better-scro…

【工具使用-Docker容器】构建自己的镜像和容器

1. 镜像和容器介绍 镜像&#xff08;Image&#xff09;是一个只读的模板&#xff0c;包含了运行某个应用所需的全部内容&#xff0c;比如&#xff1a; 操作系统&#xff08;比如 Ubuntu&#xff09;应用程序代码运行环境&#xff08;如 Python、Java、Node.js 等&#xff09;库…

Apache Shiro550 漏洞(CVE-2016-4437):原理剖析与实战 SOP

在 Web 安全领域&#xff0c;反序列化漏洞一直是威胁等级极高的存在&#xff0c;而 Apache Shiro 框架中的 Shiro550 漏洞&#xff08;CVE-2016-4437&#xff09;&#xff0c;更是因利用门槛低、影响范围广&#xff0c;成为渗透测试中频繁遇到的经典漏洞。本文将从 “原理拆解”…