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
英文地址,請注明出處:http://en.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;成為滲透測試中頻繁遇到的經典漏洞。本文將從 “原理拆解”…