It takes me less time using fopen() to download big files, but, after reading your answer, I'm not sure if it is really related to fopen vs fd or to my test environment. Anyway, I did a small patch in MHD that performs better results using fd. If you agree with that, I finally could upgrade my library to use MHD_response_from_fd-style functions and abandon fopen definitely. Firstly, consider the following example (errors handling was omitted to make it clear):
#define FILENAME "Win7.iso" // about 4.9 GB
#define USE_FOPEN
static ssize_t fileread_cb(void *handle, uint64_t offset, char *buf, size_t size) {return fread(buf, 1, size, handle);}
static void filefree_cb(void *handle) {fclose(handle);}
static int ahc_echo(void *cls, struct MHD_Connection *con, const char *url, const char *verb, const char *ver,
const char *ud, size_t *uds, void **p) {
struct MHD_Response *res;
int ret, fd;
struct stat64 buf;
FILE *file;
if (!*p) {
*p = (void *) 1;
return MHD_YES;
}
*p = NULL;
#if defined(USE_FOPEN)
file = fopen64(FILENAME, "rb");
fd = fileno(file);
fstat64(fd, &buf);
res = MHD_create_response_from_callback((uint64_t) buf.st_size, 16 * 1024, fileread_cb, file, filefree_cb);
#else
fd = open64(FILENAME, O_RDONLY);
fstat64(fd, &buf);
res = MHD_create_response_from_fd64((uint64_t) buf.st_size, fd);
#endif
ret = MHD_queue_response(con, MHD_HTTP_OK, res);
MHD_destroy_response(res);
return ret;
}
using the example above, the fopen saves 8 ~ 11 seconds (the total average time download is ~35 seconds). However, if you agree to add a new define in mhd_limits.h:
...
#ifndef MHD_FD_BLOCK_SIZE
#define MHD_FD_BLOCK_SIZE 4 * 1024
#endif
...
so MHD_create_response_from_callback() could use it:
...
response = MHD_create_response_from_callback (size,
MHD_FD_BLOCK_SIZE,
&file_reader,
NULL,
&free_callback);
...
and we could change MHD_FD_BLOCK_SIZE at build time to use a custom value in such environments.