c/c++呼び出しlibcurlライブラリhttpリクエストを送信する2つの基本的な使い方
libcurlは主に2つのhttpリクエストを送信する方式を提供しており、それぞれEasy interface方式とmulti interface方式であり、前者はブロック方式で単一のデータを送信し、後者は組み合わせ方式で複数のデータを一度に送信することができる.
一、Easy interface
libcurlのeasy interfaceは最も基本的な使い方で、簡単な流れは:1、メインスレッドでcurlを呼び出すglobal_Init(CURL_GLOBAL_ALL)初期化2、curl_を呼び出すeasy_Initはハンドルを取得します.3、curlを呼び出すeasy_setopt関数は、urlアドレス、httpヘッダ、クッキー情報、送信タイムアウト時間など、今回の送信の基本パラメータを設定します.ここで、CURLOPT_URLは必須のオプションです.4、設定が完了したらcurl_を呼び出すeasy_perform関数はデータを送信します.5、データ送信が完了したらcurl_を呼び出すeasy_cleanupクリアハンドル;6、curlを呼び出すglobal_cleanup()はクリーンアップ作業をします.
実装コード:
二、multi interface
Multi interfaceは多くのeasy interfaceにない特性を提供し、主に
1、pullインタフェースを提供し、libcurlのプログラムを使用してlibcurlをget/sendデータに呼び出すタイミングを決定することができる.
2、同一スレッドにおいて複数のデータの同時送信を実現し、プログラムをより複雑にしていない
3、プログラムは自分のファイル記述子とcurlのファイル記述子の中で同時に実行を待つことができる
4、イベントベースの処理を提供し、数千個の同時接続に伝送規模を拡大する
Multiインタフェースの使用はeasyインタフェースよりもやや複雑です.結局、multiインタフェースはeasyインタフェースに依存しており、簡単な流れは次のとおりです.
1、curl_を使うmulti_initはmulti handleを作成し、このhandlerは後続のcurl_multi_*関数でmulti handlerを使用すると、複数のデータを同時に同時転送できます.各データはeasy handlerによって作成されます.
2、転送が必要なすべてのeasyhandlerを事前に作成し、curl_を使用する必要があるeasy_setoptはそれぞれのプロパティを設定し、curl_を呼び出します.multi_add_handle関数はmulti handleに1つずつ追加されます.
3、curlを呼び出すmulti_performプロセスデータ転送、転送中にeasy handlerごとに設定されたコールバック関数または構成内容が呼び出され、プログラムは関数curl_を介してmulti_fdset、select()は、データ転送などの操作をいつ行うかを判断するために情報を抽出し、関数curl_multi_performの1つの入力パラメータはまだ伝送されているデータ量を格納し、この変数を読み取ることでmulti handlesが実行済みかどうかを判断することができ、伝送完了は伝送成功を代表するものではなく、1つ以上の伝送失敗がある可能性がある.
4、呼び出し関数curl_multi_info_readは、現在または以前に伝送された情報を取得し、メッセージキューが空になるまで関数を繰り返し呼び出し、各戻り情報には対応するeasl handlerの伝送状況が含まれる.
5.1つのeasy handler伝送が完了しても、このeasy handlerはmulti stackに留まり、curl_を呼び出す必要があるmulti_remove_handleはmulti stackから削除しcurl_を呼び出しますeasy_cleanupはそれを閉じます.
6、multi stackのすべての転送が完了した場合、curl_を呼び出すmulti_cleanupはmulti handlerを閉じ、curl_を事前に呼び出すことに注意してください.easy_cleanupは、easy handlerを1つずつ空にします.
ソース:
一、Easy interface
libcurlのeasy interfaceは最も基本的な使い方で、簡単な流れは:1、メインスレッドでcurlを呼び出すglobal_Init(CURL_GLOBAL_ALL)初期化2、curl_を呼び出すeasy_Initはハンドルを取得します.3、curlを呼び出すeasy_setopt関数は、urlアドレス、httpヘッダ、クッキー情報、送信タイムアウト時間など、今回の送信の基本パラメータを設定します.ここで、CURLOPT_URLは必須のオプションです.4、設定が完了したらcurl_を呼び出すeasy_perform関数はデータを送信します.5、データ送信が完了したらcurl_を呼び出すeasy_cleanupクリアハンドル;6、curlを呼び出すglobal_cleanup()はクリーンアップ作業をします.
実装コード:
bool send_easy_hanler(char* post_url, req_t* req)
{
//easy handler
CURL* curl = NULL;
CURLcode res = CURLE_OK;
//HTTP
struct curl_slist* headers = NULL;
char tmp_str[256] = { 0 };
// HTTP
snprintf(tmp_str, sizeof(tmp_str), "User-Agent: %s", req->user_agent_);
headers = curl_slist_append(headers, tmp_str);
snprintf(tmp_str, sizeof(tmp_str), "Accept-Language: %s", req->language_);
headers = curl_slist_append(headers, tmp_str);
snprintf(tmp_str, sizeof(tmp_str), "X-FORWORDED-FOR: %s", req->ip_.c_str());
headers = curl_slist_append(headers, tmp_str);
/* , curl_easy_init ,
libcurl ,
curl_easy_init */
curl_global_init(CURL_GLOBAL_ALL);
// easy handler
curl = curl_easy_init();
if (curl) {
// post url
curl_easy_setopt(curl, CURLOPT_URL, post_url);
// HTTP
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
//
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1);
//
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
//curl_easy_strerror
LOG(WARNING) << "curl_easy_perform() failed:" << curl_easy_strerror(res);
}
curl_slist_free_all(headers);
// . curl_easy_init
curl_easy_cleanup(curl);
// libcurl , curl_global_init 。 close
curl_global_cleanup();
}
二、multi interface
Multi interfaceは多くのeasy interfaceにない特性を提供し、主に
1、pullインタフェースを提供し、libcurlのプログラムを使用してlibcurlをget/sendデータに呼び出すタイミングを決定することができる.
2、同一スレッドにおいて複数のデータの同時送信を実現し、プログラムをより複雑にしていない
3、プログラムは自分のファイル記述子とcurlのファイル記述子の中で同時に実行を待つことができる
4、イベントベースの処理を提供し、数千個の同時接続に伝送規模を拡大する
Multiインタフェースの使用はeasyインタフェースよりもやや複雑です.結局、multiインタフェースはeasyインタフェースに依存しており、簡単な流れは次のとおりです.
1、curl_を使うmulti_initはmulti handleを作成し、このhandlerは後続のcurl_multi_*関数でmulti handlerを使用すると、複数のデータを同時に同時転送できます.各データはeasy handlerによって作成されます.
2、転送が必要なすべてのeasyhandlerを事前に作成し、curl_を使用する必要があるeasy_setoptはそれぞれのプロパティを設定し、curl_を呼び出します.multi_add_handle関数はmulti handleに1つずつ追加されます.
3、curlを呼び出すmulti_performプロセスデータ転送、転送中にeasy handlerごとに設定されたコールバック関数または構成内容が呼び出され、プログラムは関数curl_を介してmulti_fdset、select()は、データ転送などの操作をいつ行うかを判断するために情報を抽出し、関数curl_multi_performの1つの入力パラメータはまだ伝送されているデータ量を格納し、この変数を読み取ることでmulti handlesが実行済みかどうかを判断することができ、伝送完了は伝送成功を代表するものではなく、1つ以上の伝送失敗がある可能性がある.
4、呼び出し関数curl_multi_info_readは、現在または以前に伝送された情報を取得し、メッセージキューが空になるまで関数を繰り返し呼び出し、各戻り情報には対応するeasl handlerの伝送状況が含まれる.
5.1つのeasy handler伝送が完了しても、このeasy handlerはmulti stackに留まり、curl_を呼び出す必要があるmulti_remove_handleはmulti stackから削除しcurl_を呼び出しますeasy_cleanupはそれを閉じます.
6、multi stackのすべての転送が完了した場合、curl_を呼び出すmulti_cleanupはmulti handlerを閉じ、curl_を事前に呼び出すことに注意してください.easy_cleanupは、easy handlerを1つずつ空にします.
ソース:
#include
#include
#include
#include
static const char *urls[] = {
"http://www.microsoft.com",
"http://www.opensource.org",
"http://www.google.com",
"http://www.yahoo.com",
"http://www.ibm.com",
"http://www.mysql.com",
"http://www.oracle.com",
"http://www.ripe.net",
};
#define MAX 8 /* number of simultaneous transfers */
#define CNT sizeof(urls)/sizeof(char*) /* total number of transfers to do */
/* libcurl , ,
, */
static size_t cb(char *d, size_t n, size_t l, void *p)
{
/* take care of the data here, ignored in this example */
(void)d;
(void)p;
return n*l;
}
// easy handler easy handler multi handler ,
static void init(CURLM *cm, int i)
{
CURL *eh = curl_easy_init();
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, cb);
curl_easy_setopt(eh, CURLOPT_HEADER, 0L);
curl_easy_setopt(eh, CURLOPT_URL, urls[i]);
curl_easy_setopt(eh, CURLOPT_PRIVATE, urls[i]);
curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L);
// easy handler multi handler
curl_multi_add_handle(cm, eh);
}
int main(void)
{
CURLM *cm;
CURLMsg *msg;
long curl_timeo;
unsigned int C=0;
int max_fd, msgs_left, still_running = -1;//still_running multi handler
fd_set fd_read, fd_write, fd_except;
struct timeval T;
curl_global_init(CURL_GLOBAL_ALL);
cm = curl_multi_init();
// multi handler
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)MAX);
for(C = 0; C < MAX; ++C) {
init(cm, C);
}
do{
curl_multi_perform(cm, &still_running);
if(still_running) {
FD_ZERO(&fd_read);
FD_ZERO(&fd_write);
FD_ZERO(&fd_except);
// multi curl fd_set
if(!curl_multi_fdset(cm, &fd_read, &fd_write, &fd_except, &max_fd)) {
fprintf(stderr, "E: curl_multi_fdset
");
return EXIT_FAILURE;
}
if(!curl_multi_timeout(cm, &curl_timeo)) {
fprintf(stderr, "E: curl_multi_timeout
");
return EXIT_FAILURE;
}
if(curl_timeo == -1)
curl_timeo = 100;
// max_fd -1, curl_multi_perform
if(max_fd == -1) {
sleep((unsigned int)curl_timeo / 1000);
}
else {
T.tv_sec = curl_timeo/1000;
T.tv_usec = (curl_timeo%1000)*1000;
/* ,
* 0, curl_multi_perform curl
* -1, select
*/
if(0 > select(max_fd+1, &fd_read, &fd_write, &fd_except, &T)) {
fprintf(stderr, "E: select(%i,,,,%li): %i: %s
",
max_fd+1, curl_timeo, errno, strerror(errno));
return EXIT_FAILURE;
}
}
}
while((msg = curl_multi_info_read(cm, &msgs_left))) {
if(msg->msg == CURLMSG_DONE) {
char *url;
CURL *e = msg->easy_handle;
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &url);
fprintf(stderr, "R: %d - %s
",
msg->data.result, curl_easy_strerror(msg->data.result), url);
/* easy handler , easy handler multi stack ,
curl_multi_remove_handle multi stack , curl_easy_cleanup */
curl_multi_remove_handle(cm, e);
curl_easy_cleanup(e);
}
else {
fprintf(stderr, "E: CURLMsg (%d)
", msg->msg);
}
}
}while(still_running);
// multi stack , curl_multi_cleanup multi handler
curl_multi_cleanup(cm);
curl_global_cleanup();
return EXIT_SUCCESS;
}