gpt4 book ai didi

c - 在 32 位系统上使用 libevent 提供大文件 (>2GB)

转载 作者:太空宇宙 更新时间:2023-11-04 04:46:22 35 4
gpt4 key购买 nike

序言:基于 libevent v2 (evhttp)、Linux、ARM、glibc2.3.4 用 C 编写的轻量级 http 服务器

我正在尝试在 32 位系统上使用 evbuffer_add_file() 提供大文件(超过 2GB)。libevent 是使用 -D_FILE_OFFSET_BITS=64 标志编译的。这是简化的代码:

int fd = -1;
if ((fd = open(path, O_RDONLY)) < 0) {
// error handling
}

struct stat st;
if (fstat(fd, &st) < 0) {
// error handling
}

struct evbuffer *buffer = evbuffer_new();
evbuffer_set_flags(buffer, EVBUFFER_FLAG_DRAINS_TO_FD); // force using system's sendfile
evbuffer_add_file(buffer, fd, 0, st.st_size);
evhttp_send_reply(req, 200, NULL, buffer);
evbuffer_free(buffer);

st.st_size 具有正确的值,在本例中为 4913809524,但响应 header Content-Length 的值为 618842228。即使我将 Content-Length header 设置为适当的值,文件传输也会停止在 618842228 ...

我是错过了还是做错了什么?有可能吗?

提前致谢

最佳答案

正如我在评论中所说,显然问题不在 libevent 中,而在系统的 sendfile 实现中。所以通过一些解决方法,我找到了解决这个问题的方法evhttp_send_reply_(start|chunk|end) 函数系列:

    struct chunk_req_state {
struct evhttp_request *req;
int fd;
long chunksize;
off_t filesize;
off_t offset;
};

static void
chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
{
struct evbuffer *evb = evbuffer_new();
struct chunk_req_state *state = arg;
struct timeval when = { 0, 0 };
ev_ssize_t read;

if (lseek(state->fd, state->offset, SEEK_SET) == -1) {
evbuffer_free(evb);
close(state->fd);
free(state);
return;
}

read = evbuffer_read(evb, state->fd, (ev_ssize_t) state->chunksize);
if (read == -1) {
evbuffer_free(evb);
evhttp_send_reply_end(state->req);
close(state->fd);
free(state);
return;
}

evhttp_send_reply_chunk(state->req, evb);
evbuffer_free(evb);

state->offset += read;

if (state->offset < state->filesize) {
// there's more data to send
event_base_once(ebase, -1, EV_TIMEOUT, chunked_trickle_cb, state, &when);
} else {
// reached the end
evhttp_send_reply_end(state->req);
close(state->fd);
free(state);
}
}

int fd = -1;
if ((fd = open(path, O_RDONLY)) < 0) {
// error handling
}

struct stat st;
if (fstat(fd, &st) < 0) {
// error handling
}

struct timeval when = { 0, 0 };
struct chunk_req_state *state = malloc(sizeof(struct chunk_req_state));
memset(state, 0, sizeof(struct chunk_req_state));
state->req = req;
state->fd = fd;
state->chunksize = 10*1024*1024;
state->filesize = st.st_size;
state->offset = 0;
// set Content-Length to prevent chunked transfer
char *length = NULL;
spprintf(&length, 0, "%lld", st.st_size);
evhttp_add_header(evhttp_request_get_output_headers(request->req), "Content-Length", length);
free(length);
evhttp_send_reply_start(request->req, 200, NULL);
event_base_once(ebase, -1, EV_TIMEOUT, chunked_trickle_cb, state, &when);

关于c - 在 32 位系统上使用 libevent 提供大文件 (>2GB),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20482843/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com