C++利用libmicrohttpd制作交互网页端——C1

1.部署libmicrohttpd(问豆包)

2.头文件

#include <thread>
#include <fstream>
#include <vector>
#include <sstream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <algorithm>
#include <cstring>
#include <microhttpd.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>

3.定义本地端口

#define XZvisionPORT 8888

4.固定请求

cpp 复制代码
int 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 **req_cls)
{
const char *page = "<html><body>Hello, browser!</body></html>"; //  定义一个HTML页面的内容
struct MHD_Response *response; //  声明一个MHD响应结构体指针
int ret; //  声明一个整型变量用于存储返回值
response = MHD_create_response_from_buffer (strlen (page), //  创建一个持久化的HTTP响应,使用之前定义的HTML内容
(void*) page, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response); //  将响应加入队列,返回HTTP 200 OK状态码
MHD_destroy_response (response); //  销毁响应对象,释放资源
return ret; //  返回操作结果

}
int main()
{
   //自己去掉注释
   // struct MHD_Daemon *daemon;
    // daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD| MHD_USE_PEDANTIC_CHECKS, XZvisionPORT, NULL, NULL,&answer_to_connection, NULL, MHD_OPTION_END);
    // if (NULL == daemon) return 1;
    // getchar ();
    // MHD_stop_daemon (daemon);
    // return 0;
}

5.终端给内容

cpp 复制代码
int answer_to_connection1(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 **req_cls)
{
    const char* text = (const char*)cls;

    // 生成 HTML,**指定 UTF-8 编码,解决中文乱码!**
    char buf[2048];
    snprintf(buf, sizeof(buf),
        "<html><head><meta charset='utf-8'></head><body>%s</body></html>",
        text);

    struct MHD_Response *response;
    response = MHD_create_response_from_buffer(
        strlen(buf), buf, MHD_RESPMEM_MUST_COPY);

    int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
    MHD_destroy_response(response);
    return ret;
}

int main()
{
    // std::string user_text;
    // std::cout << "请输入要显示的文字:";
    // std::getline(std::cin, user_text);  // 输入一整行

    // struct MHD_Daemon *daemon;
    // daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD| MHD_USE_PEDANTIC_CHECKS, XZvisionPORT, NULL, NULL,&answer_to_connection1, (void*)user_text.c_str(), MHD_OPTION_END);
    // if (NULL == daemon) return 1;
    // getchar ();
    // MHD_stop_daemon (daemon);
    // return 0;
}

6.显示时间

cpp 复制代码
char* get_current_time()
{
    // 获取系统时间
    time_t now = time(nullptr);
    char* time_str = ctime(&now);

    // 分配新内存,返回给服务器
    char* result = new char[strlen(time_str) + 1];
    strcpy(result, time_str);

    return result; // 返回字符串
}

/*显示实时时间------刷新
    struct MHD_Daemon* daemon;

    // ==============================
    // 第六个参数传递【函数地址】!
    // ==============================
    daemon = MHD_start_daemon(
        MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_PEDANTIC_CHECKS,
        8888,
        NULL, NULL,
        &answer_to_connection2,
        (void*)get_current_time,  // ✅ 传入函数指针
        MHD_OPTION_END);

    if (!daemon) {
        cerr << "服务器启动失败!" << endl;
        return 1;
    }

    cout << "服务器已启动:http://127.0.0.1:8888" << endl;
    cout << "每次刷新页面都会更新时间!" << endl;
    getchar();

    MHD_stop_daemon(daemon);
    return 0;*/
int answer_to_connection2(
    void* cls,              // 这里 cls = 函数指针 get_current_time
    struct MHD_Connection* connection,
    const char* url,
    const char* method,
    const char* version,
    const char* upload_data,
    size_t* upload_data_size,
    void** req_cls)
{
    // ==============================
    // 1. 把 cls 转回函数指针
    // ==============================
    char* (*get_info_func)() = (char*(*)())cls;

    // ==============================
    // 2. 每次请求都调用函数,获取新时间
    // ==============================
    char* info = get_info_func();

    // ==============================
    // 3. 包装成 HTML(UTF8 中文不乱码)
    // ==============================
    char html[2048];
    snprintf(html, sizeof(html),
        "<html><head><meta charset='utf-8'></head>"
        "<body><h1>当前服务器时间:%s</h1></body></html>",
        info);

    // 发送响应
    struct MHD_Response* response = MHD_create_response_from_buffer(
        strlen(html), html, MHD_RESPMEM_MUST_COPY);

    int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
    MHD_destroy_response(response);

    // ==============================
    // 4. 【关键】释放内存!不泄漏!
    // ==============================
    delete[] info;

    return ret;
}
int main()
{
// struct MHD_Daemon *daemon;

    // daemon = MHD_start_daemon(
    //     MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_PEDANTIC_CHECKS,
    //     8888,
    //     NULL, NULL,
    //     &answer_to_connection3,
    //     NULL,
    //     MHD_OPTION_END);

    // if (!daemon) {
    //     cerr << "服务器启动失败!" << endl;
    //     return 1;
    // }

    // cout << "服务器已启动 : 端口 8888" << endl;
    // cout << "现在用浏览器访问,会打印所有请求信息!" << endl;

    // getchar();
    // MHD_stop_daemon(daemon);
    // return 0;

}

7.分级跳转

cpp 复制代码
// 发送 HTML 响应(中文不乱码)
static int send_html(struct MHD_Connection *conn, const char *html)
{
    struct MHD_Response *resp = MHD_create_response_from_buffer(
        strlen(html), (void*)html, MHD_RESPMEM_PERSISTENT);

    // ✅ 关键:告诉浏览器用 UTF-8 解析
    MHD_add_response_header(resp, "Content-Type", "text/html; charset=utf-8");

    int ret = MHD_queue_response(conn, MHD_HTTP_OK, resp);
    MHD_destroy_response(resp);
    return ret;
}

// 发送 404 响应
static int send_404(struct MHD_Connection *conn)
{
    const char *page = "<html><head><meta charset=utf-8></head><body><h1>404 页面未找到</h1></body></html>";
    struct MHD_Response *resp = MHD_create_response_from_buffer(
        strlen(page), (void*)page, MHD_RESPMEM_PERSISTENT);

    MHD_add_response_header(resp, "Content-Type", "text/html; charset=utf-8");

    int ret = MHD_queue_response(conn, MHD_HTTP_NOT_FOUND, resp);
    MHD_destroy_response(resp);
    return ret;
}
static int answer_to_connection4(
    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 **req_cls)
{
    // 只处理 GET
    if (strcmp(method, "GET") != 0) {
        return MHD_NO;
    }

    // ======================
    // 首页 /index.html
    // ======================
    if (strcmp(url, "/index.html") == 0 || strcmp(url, "/index.htm") == 0) {
        const char *page =
            "<html>"
            "<head><meta charset=\"utf-8\"></head>"
            "<body>"
            "<h1>虚拟首页</h1>"
            "<p>这是动态生成的 index.html</p>"
            "<a href=\"/another.html\">跳转到 another.html</a>"
            "</body>"
            "</html>";
        return send_html(connection, page);
    }

    // ======================
    // 另一个页面 /another.html
    // ======================
    else if (strcmp(url, "/another.html") == 0) {
        const char *page =
            "<html>"
            "<head><meta charset=\"utf-8\"></head>"
            "<body>"
            "<h1>第二个页面</h1>"
            "<p>这是动态生成的 another.html</p>"
            "<a href=\"/index.html\">返回首页</a>"
            "</body>"
            "</html>";
        return send_html(connection, page);
    }

    // ======================
    // 404
    // ======================
    else {
        return send_404(connection);
    }

    return MHD_NO;
}

int main()
{

struct MHD_Daemon *daemon;

    daemon = MHD_start_daemon(
        MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_PEDANTIC_CHECKS,
        8888,
        NULL, NULL,
        &answer_to_connection4,
        NULL,
        MHD_OPTION_END);

    if (!daemon) {
        cerr << "服务器启动失败!" << endl;
        return 1;
    }

    cout << "服务器已启动 : 端口 8888" << endl;
    cout << "现在用浏览器访问,会打印所有请求信息!" << endl;

    getchar();
    MHD_stop_daemon(daemon);
    return 0;

}
相关推荐
Gauss松鼠会1 小时前
【GaussDB】GaussDB SMP特性调优详解
java·服务器·前端·数据库·sql·算法·gaussdb
fpcc1 小时前
C++编程实践—C++实现类似Qt的信号槽机制
c++·qt
格发许可优化管理系统2 小时前
Mentor许可证使用规定全解析
java·大数据·c语言·开发语言·c++
郝学胜_神的一滴2 小时前
Qt 高级开发 030:QListWidget 右键菜单全解,从策略配置到精准删除的优雅实现
c++·qt
JAVA面经实录9172 小时前
Redis 知识体系(完整版)
java·redis·nosql数据库·nosql
武子康2 小时前
Java-21 深入浅出 MyBatis 手写ORM框架2 手写Resources、MappedStatment、XMLBuilder等
java·后端
Full Stack Developme2 小时前
Java DFA算法
java·python·算法
Yukinaaaa2 小时前
以“轮盘数组”思维彻底搞懂并实现阻塞队列
java·服务器·ide·安全·javaee·阻塞队列·轮盘数组
夕除2 小时前
AOP 实现 Redis 缓存切面解析
java·开发语言·python