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?
我也很感激,如果有人建议你应该避免卷曲。也许有人可以给我一个已经存在的信息来源的链接?
3 个解决方案
#1
11
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_easy_init(),初始化容易,
-
curl_global_init()
, most of the case the flag option has to beCURL_GLOBAL_ALL
- curl_global_init(),大多数情况下flag选项必须是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_easy_cleanup()当你完成你已声明的句柄时,
-
curl_global_cleanup()
when you're done with libcurl, - 当你完成libcurl时curl_global_cleanup(),
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 sleep
or _sleep
or replace 5000 by 5.
如果您对睡眠有任何问题,请尝试通过睡眠或_sleep替换它或将5000替换为5。
#2
4
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()更改url,然后再拨打第二个电话?这应该没有任何错误,因为该函数不会更改任何先前设置的句柄选项。这是一个简短的工作示例:
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.*.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 no since 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()不会重置任何选项,你的代码应该没问题,你可以坚持只更改像curl_easy_setoption(curl,CURLOPT_URL,
#3
3
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.
你要么重置它XOR清理它(再次分配curl_easy_init()的返回值之前) - 两者都做不好。有关详细信息,请参阅文档。
#1
11
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_easy_init(),初始化容易,
-
curl_global_init()
, most of the case the flag option has to beCURL_GLOBAL_ALL
- curl_global_init(),大多数情况下flag选项必须是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_easy_cleanup()当你完成你已声明的句柄时,
-
curl_global_cleanup()
when you're done with libcurl, - 当你完成libcurl时curl_global_cleanup(),
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 sleep
or _sleep
or replace 5000 by 5.
如果您对睡眠有任何问题,请尝试通过睡眠或_sleep替换它或将5000替换为5。
#2
4
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()更改url,然后再拨打第二个电话?这应该没有任何错误,因为该函数不会更改任何先前设置的句柄选项。这是一个简短的工作示例:
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.*.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 no since 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()不会重置任何选项,你的代码应该没问题,你可以坚持只更改像curl_easy_setoption(curl,CURLOPT_URL,
#3
3
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.
你要么重置它XOR清理它(再次分配curl_easy_init()的返回值之前) - 两者都做不好。有关详细信息,请参阅文档。