C程序使用libcurl获取本地服务器数据时出现curl failed writing body错误
搞定Curl "failed writing body" 错误的方案
Hey,我一眼就看到问题出在哪了——你的write_data回调函数返回值不对!Curl对这个回调的返回值有严格要求,必须返回实际处理的总字节数,也就是size * nmemb,而不是你现在返回的size。当返回的数值和Curl预期的字节数不匹配时,它就会判定写入失败,抛出"failed writing body"的错误。
为啥会报错?
先看你现在的回调:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { return size; }
这里size是单个数据块的字节大小,nmemb是数据块的数量,总字节数是两者相乘。你只返回了size,相当于告诉Curl"我只处理了1个数据块的大小",但服务器返回的数据可能分成了多个块,Curl发现数据没被完整处理,直接就报错了。
最简单的修复方案
如果只是想让请求正常完成,不需要保存返回的数据,直接返回总字节数就行:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { // 告诉Curl所有数据都已处理完成 return size * nmemb; }
进阶:保存返回的数据
要是你需要把服务器返回的内容存下来,可以用userp参数传递存储载体,比如动态内存或者文件指针:
示例1:存到动态内存里
// 定义一个结构体来存数据和长度 typedef struct { char *data; size_t len; } MemoryBuffer; size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { MemoryBuffer *buf = (MemoryBuffer *)userp; size_t total_bytes = size * nmemb; size_t new_len = buf->len + total_bytes; // 重新分配内存,多留一个字节存字符串结束符 buf->data = realloc(buf->data, new_len + 1); if (!buf->data) { // 内存分配失败,返回0让Curl终止请求 return 0; } // 把新数据复制到内存里 memcpy(buf->data + buf->len, buffer, total_bytes); buf->len = new_len; buf->data[buf->len] = '\0'; // 确保是合法的C字符串 return total_bytes; } // 在main里这么用 int main() { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if (curl) { MemoryBuffer chunk = {NULL, 0}; curl_easy_setopt(curl, CURLOPT_URL, "localhost:3000/employees/2"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); // 把我们的内存结构体传递给回调 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk); res = curl_easy_perform(curl); // 这里可以用chunk.data拿到返回的内容 if (res == CURLE_OK && chunk.data) { printf("Response: %s\n", chunk.data); } // 用完记得释放内存! if (chunk.data) free(chunk.data); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
示例2:直接存到文件
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { FILE *fp = (FILE *)userp; // 直接用fwrite返回写入的数量,和Curl预期的一致 return fwrite(buffer, size, nmemb, fp); } // main里的用法 int main() { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if (curl) { FILE *fp = fopen("response.txt", "wb"); if (fp) { curl_easy_setopt(curl, CURLOPT_URL, "localhost:3000/employees/2"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); res = curl_easy_perform(curl); fclose(fp); } curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
最后再检查俩点
- 先确认你的本地服务器
localhost:3000真的正常跑着,用命令行curl localhost:3000/employees/2测试下,看看能不能拿到数据。 - 别忘了在请求结束后调用
curl_easy_cleanup(curl)和curl_global_cleanup(),不然可能会有内存泄漏。
内容的提问来源于stack exchange,提问作者testalucida
相关产品推荐
相关产品推荐

