libevent file文件读取事件

#include <iostream>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <event2/event.h>

using namespace std;


static void READ_CB(int sock, short which , void* arg)
{
    char szBuff[1024];
    memset(szBuff, 0, sizeof(szBuff));
    
    int rd_len = read(sock, szBuff, sizeof(szBuff)-1);
    if (rd_len > 0)
    {
        cout<<szBuff<<endl;
    }
    
}
int main()
{
    //初始化配置上下文
    event_config *pevconf = event_config_new();
    if (!pevconf)
    {
        cerr<<"event_config_new error"<<endl;
        return -1;
    }
    //EV_FEATURE_FDS:需要一个允许文件描述符和套接字的事件方法
    event_config_require_features(pevconf, EV_FEATURE_FDS);
    event_base *pevbs = event_base_new_with_config(pevconf);
    if (!pevbs)
    {
        cerr<<"event_base_new_with_config error"<<endl;
        return -1;
    }
    
    //以非阻塞性读取打开系统文件
    int sock = open("/var/log/auth.log", O_RDONLY | O_NONBLOCK, 0);
    
    //将sock文件移动到文件末尾,否则会从文件开头开始读取
    lseek(sock, 0, SEEK_END);
    //文件读取、持久性事件
    event* pevf = event_new(pevbs, sock, EV_READ|EV_PERSIST, READ_CB, event_self_cbarg());
    if (!pevf)
    {
        cerr<<"event_new error"<<endl;
    }
    event_add(pevf, NULL);
    
    event_base_dispatch(pevbs);
    event_config_free(pevconf);
    event_base_free(pevbs);
    return 0;
}


可以进行linux终端登陆来进行测试
./event_file
Feb 5 01:29:31 ubuntu1 sshd[17635]: Accepted password for zhangsan from 192.168.202.1 port 52975 ssh2
Feb 5 01:29:31 ubuntu1 sshd[17635]: pam_unix(sshd:session): session opened for user zhangsan by (uid=0)

Feb 5 01:29:31 ubuntu1 systemd-logind[910]: New session 506 of user zhangsan.

Feb 5 01:31:09 ubuntu1 sshd[17635]: pam_unix(sshd:session): session closed for user zhangsan

Feb 5 01:31:09 ubuntu1 systemd-logind[910]: Removed session 506.

在使用 libevent 实现 HTTP 服务器的过程中,处理文件上传功能通常涉及解析客户端发送的 multipart/form-data 格式请求体。libevent 提供了基本的 HTTP 服务支持,但对于复杂的请求体解析(如文件上传),需要手动实现解析逻辑。 ### 实现文件上传的基本思路 1. **监听 HTTP 请求**:通过 `evhttp` 接口创建 HTTP 服务器并绑定请求处理回调函数。 2. **获取请求类型**:判断请求是否为 `POST` 类型,并检查 `Content-Type` 是否为 `multipart/form-data`。 3. **读取请求体**:使用 `evbuffer` 接口从请求中读取完整的请求体数据。 4. **解析 multipart/form-data**:手动解析 multipart 数据,提取文件内容和文件名。 5. **保存文件**:将提取到的文件内容写入本地文件系统。 ### 示例代码 以下是一个简单的示例代码,展示如何使用 libevent 实现基本的文件上传处理逻辑: ```c #include <event2/event.h> #include <event2/http.h> #include <event2/buffer.h> #include <event2/util.h> #include <event2/keyvalq_struct.h> #include <stdio.h> #include <string.h> // 解析 multipart/form-data 的边界字符串 static char *extract_boundary(const char *content_type) { const char *boundary_start = strstr(content_type, "boundary="); if (!boundary_start) return NULL; boundary_start += strlen("boundary="); const char *end = strchr(boundary_start, ';'); size_t len = end ? (size_t)(end - boundary_start) : strlen(boundary_start); char *boundary = malloc(len + 3); strcpy(boundary, "--"); strncpy(boundary + 2, boundary_start, len); boundary[len + 2] = '\0'; return boundary; } // 处理上传请求 void handle_upload(struct evhttp_request *req, void *arg) { struct evbuffer *buf = evbuffer_new(); evbuffer_add_buffer(buf, req->input_buffer); size_t len = evbuffer_get_length(buf); char *data = malloc(len + 1); evbuffer_remove(buf, data, len); data[len] = '\0'; // 获取 Content-Type const char *content_type = evhttp_find_header(req->input_headers, "Content-Type"); if (!content_type || !strstr(content_type, "multipart/form-data")) { evhttp_send_error(req, HTTP_BADREQUEST, "Invalid Content-Type"); free(data); evbuffer_free(buf); return; } // 提取 boundary char *boundary = extract_boundary(content_type); if (!boundary) { evhttp_send_error(req, HTTP_BADREQUEST, "Missing boundary"); free(data); evbuffer_free(buf); return; } // 简单解析 multipart 数据 char *token = strtok(data, boundary); while (token) { if (strstr(token, "filename=")) { // 提取文件名 const char *filename_start = strstr(token, "filename=\"") + strlen("filename=\""); char *filename_end = strchr(filename_start, '"'); char filename[256]; strncpy(filename, filename_start, filename_end - filename_start); filename[filename_end - filename_start] = '\0'; // 提取文件内容 const char *file_data_start = strstr(token, "\r\n\r\n") + 4; const char *file_data_end = strstr(file_data_start, "\r\n"); size_t file_data_len = file_data_end - file_data_start; // 写入文件 FILE *fp = fopen(filename, "wb"); if (fp) { fwrite(file_data_start, 1, file_data_len, fp); fclose(fp); printf("File %s saved successfully\n", filename); } else { printf("Failed to save file %s\n", filename); } } token = strtok(NULL, boundary); } free(boundary); free(data); evbuffer_free(buf); struct evbuffer *response = evbuffer_new(); evbuffer_add_printf(response, "File uploaded successfully"); evhttp_send_reply(req, HTTP_OK, "OK", response); evbuffer_free(response); } int main(int argc, char **argv) { struct event_base *base = event_base_new(); struct evhttp *http = evhttp_new(base); evhttp_bind_socket(http, "0.0.0.0", 8080); evhttp_set_gencb(http, handle_upload, NULL); printf("Starting HTTP server on port 8080...\n"); event_base_dispatch(base); evhttp_free(http); event_base_free(base); return 0; } ``` ### 注意事项 - **性能优化**:上述示例仅用于演示,实际应用中应考虑使用更高效的解析方式,避免一次性将整个请求体加载到内存中。 - **安全性**:需对上传文件名进行清理,防止路径穿越攻击(如 `../`)。 - **错误处理**:示例中省略了部分错误处理逻辑,实际开发中应加强健壮性处理。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值