C语言 如何正确重用卷曲手柄
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14911156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to properly reuse a curl handle
提问by user1494517
I want to properly reuse a curl handle, so that it won't give me errors and function normally.
我想正确地重用 curl 句柄,这样它就不会给我错误和正常运行。
Suppose I have this piece of code:
假设我有这段代码:
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0...");
curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com");
curl_easy_perform(curl);
curl_easy_setopt(curl, CURLOPT_URL, "http://www.bbc.com");
curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
Would this be a good or correct way of reusing a curl handle? Or do I need to use curl_easy_reset()on that handle?
这是重用卷曲手柄的好方法或正确方法吗?还是我需要curl_easy_reset()在那个手柄上使用?
I would also appreciate if anyone suggested what you should avoid doing in curl. Maybe someone could give me a link to an already existing source of information?
如果有人建议您应该避免在 curl 中做什么,我也将不胜感激。也许有人可以给我一个现有信息来源的链接?
回答by borderless
When you use the environment libcurl on the easy interface, you first have to call :
在easy界面上使用环境libcurl时,首先必须调用:
curl_easy_init(), which init the easy handle,curl_global_init(), most of the case the flag option has to beCURL_GLOBAL_ALL
curl_easy_init(), 初始化简单句柄,curl_global_init(),大多数情况下标志选项必须是CURL_GLOBAL_ALL
Each of those two functions is called just once at the beginning and need their opposite clean up :
这两个函数中的每一个在开始时都只调用一次,需要进行相反的清理:
curl_easy_cleanup()when you've finished handles you've declare,curl_global_cleanup()when you're done with libcurl,
curl_easy_cleanup()当你完成你声明的句柄时,curl_global_cleanup()当你完成 libcurl 时,
For better results check errors as much as you can. Libcurl provides curl_easy_strerror()function for that. It returns a string describing the CURLcode error. Also, some functions return the value
CURL_OK or a specific integer if everything is OK.
为了获得更好的结果,请尽可能多地检查错误。Libcurl 为此提供了curl_easy_strerror()功能。它返回一个描述 CURLcode 错误的字符串。此外,如果一切正常,某些函数会返回值 CURL_OK 或特定整数。
For instance, here's the proper way to use CURLOPT_URL option :
例如,这是使用 CURLOPT_URL 选项的正确方法:
#include <curl.h>
int main(void)
{
/* declaration of an object CURL */
CURL *handle;
/* result of the whole process */
CURLcode result;
/* the first functions */
/* set up the program environment that libcurl needs */
curl_global_init(CURL_GLOBAL_ALL);
/* curl_easy_init() returns a CURL easy handle that you're gonna reuse in other easy functions*/
handle = curl_easy_init();
/* if everything's all right with the easy handle... */
if(handle)
{
/* ...you can list the easy functions */
/* here we just gonna try to get the source code of http://example.com */
curl_easy_setopt(handle, CURLOPT_URL, "http://example.com");
/* but in that case we also tell libcurl to follow redirection */
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
/* perform, then store the expected code in 'result'*/
result = curl_easy_perform(handle);
/* Check for errors */
if(result != CURLE_OK)
{
/* if errors have occured, tell us wath's wrong with 'result'*/
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));
return 1;
}
}
/* if something's gone wrong with curl at the beginning, we'll appriciate that piece of code */
else
{
fprintf(stderr, "Curl init failed!\n");
return 1;
}
/* cleanup since you've used curl_easy_init */
curl_easy_cleanup(handle);
/* this function releases resources acquired by curl_global_init() */
curl_global_cleanup();
/* make the programme stopping for avoiding the console closing befor you can see anything */
system("PAUSE");
return 0;
}
If you want to reuse that handle for a totally different purpose you'd better use different CURL easy handles. Still your code should work fine but i would use different handles because it's obviously two seperate operations.
如果您想为完全不同的目的重用该句柄,您最好使用不同的 CURL 简易句柄。您的代码仍然可以正常工作,但我会使用不同的句柄,因为这显然是两个单独的操作。
However sometimes you'll need to work with the same handle and if you don't want to do reset it automatically, use the appropriate function :
但是有时您需要使用相同的句柄,如果您不想自动重置它,请使用适当的功能:
void curl_easy_reset(CURL *handle);
Note that it does not change live connections, the Session ID cache, the DNS cache, the cookies and shares from the handle.
请注意,它不会更改实时连接、会话 ID 缓存、DNS 缓存、cookie 和句柄中的共享。
I haven't tried it but with your code it should give us something like that :
我还没有尝试过,但是使用您的代码,它应该给我们类似的东西:
#include <curl.h>
int main(void)
{
CURL *handle;
CURLcode result;
int error = 0;
int error2 = 0;
curl_global_init(CURL_GLOBAL_ALL);
handle = curl_easy_init();
if(handle)
{
curl_easy_setopt(handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2) Gecko/20100115 Firefox/3.6");
curl_easy_setopt(handle, CURLOPT_URL, "http://www.google.com");
result = curl_easy_perform(handle);
if(result != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));
error++;
}
Sleep(5000); // make a pause if you working on console application
curl_easy_reset(handle);
curl_easy_setopt(handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2) Gecko/20100115 Firefox/3.6"); // have to write it again
curl_easy_setopt(handle, CURLOPT_URL, "http://www.bbc.com");
result = curl_easy_perform(handle);
if(result != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(result));
error2++;
}
if(error == 1 || error2 == 1)
{
return 1;
}
}
else
{
fprintf(stderr, "Curl init failed!\n");
return 1;
}
curl_easy_cleanup(handle);
curl_global_cleanup();
system("PAUSE");
return 0;
}
If you have any problem with Sleep, try to replace it by sleepor _sleepor replace 5000 by 5.
如果您有任何问题Sleep,请尝试将其替换为sleep或_sleep或将 5000 替换为 5。
回答by Cyclonecode
If I understand the question correctly you would like to know if you can make a call to curl_easy_perform()and then only change the url through curl_easy_setoption()and then make a second call? This should work without any errors since the function doesn't change any previously set options for the handle. This is a short working example:
如果我正确理解了这个问题,您想知道您是否可以拨打电话curl_easy_perform(),然后只更改网址curl_easy_setoption(),然后再拨打第二个电话?这应该没有任何错误,因为该函数不会更改任何先前设置的句柄选项。这是一个简短的工作示例:
size_t writeCallback(char* contents, size_t size, size_t nmemb, std::string* buffer) {
size_t realsize = size * nmemb;
if(buffer == NULL) {
return 0;
}
buffer->append(contents, realsize);
return realsize;
}
int main(int argc, char** argv) {
std::string buffer;
// initialize global
curl_global_init(CURL_GLOBAL_ALL);
// start a libcurl easy session
CURL* ch = curl_easy_init();
// this options will only be set once
curl_easy_setopt(ch, CURLOPT_VERBOSE, 0);
curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(ch, CURLOPT_USERAGENT, "Crawler");
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, &writeCallback);
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &buffer);
std::vector<const char*> queue;
queue.push_back("http://www.google.com");
queue.push_back("http://www.stackoverflow.com");
const char* url;
CURLcode code;
do {
// grab an url from the queue
url = queue.back();
queue.pop_back();
// only change this option for the handle
// the rest will stay intact
curl_easy_setopt(ch, CURLOPT_URL, url);
// perform transfer
code = curl_easy_perform(ch);
// check if everything went fine
if(code != CURLE_OK) {
}
// clear the buffer
buffer.clear();
} while(queue.size() > 0);
// cleanup
curl_easy_cleanup(ch);
curl_global_cleanup();
return 0;
}
Or do I need to use curl_easy_reset() on that handle?
或者我需要在那个手柄上使用 curl_easy_reset() 吗?
The answer is nosince curl_easy_perform()not will reset any options your code should be fine and you can stick with only changing the url like curl_easy_setoption(curl, CURLOPT_URL, <newurl>);.
答案是否定的,因为curl_easy_perform()不会重置任何选项,您的代码应该没问题,您可以坚持只更改 url 之类的curl_easy_setoption(curl, CURLOPT_URL, <newurl>);.
回答by Cyclonecode
Or do I need to use curl_easy_reset() on that handle?
或者我需要在那个手柄上使用 curl_easy_reset() 吗?
You either reset it XOR clean it up (before assigning the return value of curl_easy_init()again) - doing both is not good. For more info, see the documentation.
你要么重置它异或清理它(在curl_easy_init()再次分配返回值之前) - 两者都做不好。有关更多信息,请参阅文档。

