为何libcurl的curl_easy_perform仅设置CURLOPT_READFUNCTION后才不阻塞?
嘿,我来帮你理清楚这个问题的核心原因,其实这和libcurl处理POST请求的默认逻辑直接相关:
1. 未设置READFUNCTION时阻塞的根源
当你把CURLOPT_POST设为1时,libcurl会默认认为你要发送POST请求体数据。但如果你没有明确指定数据来源(比如通过CURLOPT_POSTFIELDS传字符串、或者配置文件上传等),libcurl的默认行为是:它会尝试从**标准输入(stdin)**读取POST数据。
这就是你的程序卡住的原因——它一直在等你从控制台输入数据,但你没有做这个操作,所以curl_easy_perform就一直阻塞在那里了。
2. 设置READFUNCTION后不阻塞的原因
当你配置了自定义的CURLOPT_READFUNCTION和CURLOPT_READDATA,libcurl就会调用你提供的readcb函数来获取POST数据。如果你的readcb函数返回了0(这是libcurl识别的「没有更多数据要发送」的信号),libcurl就会明白:不需要再等待数据了,直接发送一个空的POST请求体,然后继续完成整个请求流程,自然就不会阻塞了。
不过这里要注意:你的代码是调用登录接口,而且设置了Content-Type: application/json,这种场景下接口大概率需要接收登录参数(比如用户名、密码),现在的方式虽然不阻塞,但发送空请求体几乎肯定会导致接口返回错误。
3. 针对你场景的正确解决方法
根据你的需求,推荐直接用CURLOPT_POSTFIELDS指定JSON格式的请求体:
// 构造登录用的JSON数据(替换成你的实际参数) const std::string loginJson = R"({"username":"your_account","password":"your_pass"})"; // 将JSON字符串传给libcurl curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, loginJson.c_str()); // 可选:精确指定数据长度,避免libcurl自动计算(如果是动态分配的内存更推荐) curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDSIZE, loginJson.size());
如果你的场景确实不需要发送POST请求体(虽然登录接口一般都需要),也可以直接告诉libcurl不要等待数据:
// 方式1:设置空的POST字段 curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, ""); // 方式2:直接指定POST数据长度为0 curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDSIZE, 0L);
这样既不用配置自定义的READFUNCTION,也不会出现阻塞问题。
内容的提问来源于stack exchange,提问作者Kelvin Poon

