libevent的安装

从github上下载压缩包

libevent的github下载的地址
在这里插入图片描述

将压缩包拷贝到unbuntu22.04的虚拟机上面

wuhaonan:match-game$ls
libevent-2.1.12-stable  libevent-2.1.12-stable.tar.gz
wuhaonan:match-game$tar -zxvf libevent-2.1.12-stable.tar.gz
cd libevent-2.1.12-stable
wuhaonan:libevent-2.1.12-stable	
wuhaonan:libevent-2.1.12-stable$cd cmake/
wuhaonan:libevent-2.1.12-stable$mkdir build && cd build
wuhaonan:build$ls
wuhaonan:build$cmake ..
wuhaonan:build$make
wuhaonan:build$sudo make install
wuhaonan:build$sudo ldconfig  # 更新库缓存
wuhaonan:build$ls /usr/local/include/event2/event.h  # 系统路径

测试libevent是否安装成功

demo.c

#include <event2/event.h>
#include <stdio.h>
/*
# 默认系统路径(/usr/local)
gcc demo.c -o demo -levent

# 自定义路径(如$HOME/local)
gcc demo.c -o demo -I$HOME/local/include -L$HOME/local/lib -levent

解决运行时库路径问题
若安装到非系统路径,需设置LD_LIBRARY_PATH:

bash
复制
export LD_LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH
./demo
*/
int main() {
    struct event_base *base = event_base_new();
    printf("LibEvent initialized successfully!\n");
    event_base_free(base);
    return 0;
}

执行gcc demo.c -o demo -levent

wuhaonan:match-game$gcc demo.c -o demo -levent
wuhaonan:match-game$./demo 
LibEvent initialized successfully!

经过测试安装成功

简单测试libevent

注:还需要安装cJSON

#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include <cjson/cJSON.h> // cJSON 头文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// GET请求处理函数
// 第一个参数req是HTTP请求对象,第二个参数arg是用户自定义参数,这里没有使用
void handle_get(struct evhttp_request *req, void *arg)
{
    // 获取请求URI 将http请求的uri作为参数传递
    const char *uri = evhttp_request_get_uri(req);
    if (uri == NULL) {
        printf("URI is NULL\n");
        return;
    }
    // 打印请求URI
    printf("GET %s\n", uri);

    // 创建JSON响应
    cJSON *root = cJSON_CreateObject(); // 创建JSON对象 准备构建响应数据
    if (root == NULL)
    {
        printf("创建JSON对象失败\n");
        return;
    }

    // 构建响应数据
    cJSON_AddStringToObject(root, "status", "success"); // 添加字符串键值对
    cJSON_AddStringToObject(root, "message", "欢迎使用JSON服务"); // 添加字符串键值对

    // 构建JSON响应字符串 将JSON对象转换为JSON字符串
    char *json_str = cJSON_Print(root); // 打印JSON对象
    if (json_str == NULL)
    {
        printf("打印JSON对象失败\n");
        cJSON_Delete(root); // 释放JSON对象
        return;
    }

    struct evbuffer *buf = evbuffer_new(); // 创建缓冲区
    if (buf == NULL)
    {
        printf("创建缓冲区失败\n");
        cJSON_free(json_str); // 释放JSON字符串
        cJSON_Delete(root); // 释放JSON对象
        return;
    }

    evbuffer_add_printf(buf, "%s", json_str); // 添加JSON字符串到缓冲区
    
    // 设置JSON响应头
    // 为HTTP响应设置Content-Type头,指定响应的内容类型为JSON。这有助于客户端(如浏览器或API调用者)正确解析服务器返回的数据格式。
    evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "application/json"); // 设置响应头
    evhttp_add_header(evhttp_request_get_output_headers(req), "Access-Control-Allow-Origin", "*"); // 添加跨域支持
    evhttp_send_reply(req, HTTP_OK, "OK", buf); // 发送HTTP响应

    // 释放资源
    evbuffer_free(buf); // 释放缓冲区
    cJSON_Delete(root); // 释放JSON对象
    free(json_str); // 释放JSON字符串
}

// POST请求处理函数(JSON解析)
void handle_post(struct evhttp_request *req, void *arg)
{
    // 获取请求体中的数据
    struct evbuffer *input_buf = evhttp_request_get_input_buffer(req); // 获取请求输入缓冲区
    if (input_buf == NULL)  
    {
        printf("获取请求输入缓冲区失败\n");
        return;
    }
    size_t len = evbuffer_get_length(input_buf); // 获取输入缓冲区长度
    if (len == 0)
    {
        printf("输入缓冲区为空\n");
        return;
    }
    // +1是为了在结尾添加一个空字符,以便于字符串处理
    char *post_data = (char*)malloc(len + 1); // 分配内存
    if (post_data == NULL)
    {
        printf("分配内存失败\n");
        return;
    }
    // 从输入缓冲区中拷贝数据到post_data
    evbuffer_copyout(input_buf, post_data, len); // 拷贝缓冲区数据到post_data
    post_data[len] = '\0'; // 结尾添加空字符

    printf("原始POST数据: %s\n", post_data); // 打印原始POST数据

    // 解析JSON数据
    cJSON *root = cJSON_Parse(post_data); // 解析JSON字符串
    struct evbuffer *retbuf = evbuffer_new(); // 创建缓冲区
    if (retbuf == NULL)
    {
        printf("创建缓冲区失败\n");
        free(post_data); // 释放内存
        cJSON_Delete(root); // 释放JSON对象
        return;
    }
    if(!root){
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL)
        {
            fprintf(stderr, "JSON解析错误前: %s\n", error_ptr);
        }
        evbuffer_add_printf(retbuf, "{\"error\":\"Invalid JSON\"}");
        evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", retbuf);
        goto cleanup;
    }

    // 提取JSON字段 
    cJSON *username = cJSON_GetObjectItemCaseSensitive(root, "username"); // 获取username字段
    cJSON *age = cJSON_GetObjectItemCaseSensitive(root, "age"); // 获取age字段
    if(username == NULL || age == NULL) {
        printf("JSON数据不完整\n");
        evbuffer_add_printf(retbuf, "{\"error\":\"JSON数据不完整\"}");
        evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", retbuf);
        goto cleanup;
    }

    // 构建响应JSON
    cJSON *response = cJSON_CreateObject(); // 创建JSON对象
    if (cJSON_IsString(username) && cJSON_IsNumber(age)) {
        cJSON_AddStringToObject(response, "status", "success");
        cJSON_AddStringToObject(response, "username", username->valuestring);
        cJSON_AddNumberToObject(response, "age", age->valueint);
    } else {
        cJSON_AddStringToObject(response, "error", "字段格式错误");
    }

    // 发送响应
    char *response_str = cJSON_PrintUnformatted(response); // 打印JSON对象
    evbuffer_add_printf(retbuf, "%s", response_str); // 添加JSON字符串到缓冲区
    evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "application/json"); // 设置响应头
    evhttp_add_header(evhttp_request_get_output_headers(req), "Access-Control-Allow-Origin", "*"); // 添加跨域支持
    evhttp_send_reply(req, HTTP_OK, "OK", retbuf); // 发送HTTP响应

    cleanup:
    // 资源清理
    evbuffer_free(retbuf);
    cJSON_Delete(root);
    if (response) cJSON_Delete(response); // 确保response不为NULL
    free(post_data);
    if (response_str) free(response_str); // 确保response_str不为NULL
}

/*
 gcc -o demo demo.c -levent -lcjson

# GET请求测试
curl "http://localhost:8080/api/get?name=John"

# POST测试(JSON格式)
curl -X POST -H "Content-Type: application/json" \
-d '{"username":"张三","age":25}' \
http://localhost:8080/api/post

# 响应结果:
欢迎使用libevent服务!
GET参数 name=John
*/
int main(void)
{
    // 事件库会监听各种事件(例如网络套接字上的读写事件,定时器事件等),并在这些事件发生时调用相应的回调函数来处理这些事件。
    struct event_base *base = event_base_new(); // 创建事件库 
    if(base == NULL) {
        printf("创建事件库失败\n");
        return 1;
    }

    // 创建HTTP服务器
    struct evhttp *http = evhttp_new(base); // 创建HTTP服务器
    if(http == NULL) {
        printf("创建HTTP服务器失败\n");
        return 1;
    }

    // 设置HTTP服务器的监听地址和端口
    if(evhttp_bind_socket(http, "0.0.0.0", 8080) != 0) {
        printf("绑定HTTP服务器失败\n");
        return 1;
    }

    // 设置HTTP服务器的回调函数
    evhttp_set_cb(http, "/api/get", handle_get, NULL); // 设置GET请求的回调函数
    evhttp_set_cb(http, "/api/post", handle_post, NULL); // 设置POST请求的回调函数

    printf("HTTP服务器启动成功,监听端口8080\n");
    // 事件循环,监听并处理事件 会阻塞,直到事件循环结束    
    event_base_dispatch(base); // 启动事件循环

    // 释放资源
    evhttp_free(http); // 释放HTTP服务器
    event_base_free(base); // 释放事件库
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值