久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

使用multi curl進(jìn)行http并發(fā)訪問(wèn)

 wtkc 2014-11-22

    curl是一款利用URL語(yǔ)法進(jìn)行文件傳輸?shù)墓ぞ撸С侄喾N協(xié)議,,包括FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET等,我們既可以在命令行上使用它,,也可以利用 libcurl進(jìn)行相關(guān)編程,。相信大部分同學(xué)都應(yīng)該使用過(guò)libcurl的easy 接口,,easy接口的使用非常的簡(jiǎn)單,curl_easy_init用來(lái)初始化一個(gè)easy curl對(duì)象,,curl_easy_setopt對(duì)easy curl對(duì)象進(jìn)行相關(guān)設(shè)置,,最后curl_easy_perform執(zhí)行curl請(qǐng)求,,返回相應(yīng)結(jié)果。easy接口是阻塞的,,也就是說(shuō)必須等到上一個(gè)curl請(qǐng)求執(zhí)行完后,,下一個(gè)curl請(qǐng)求才能繼續(xù)執(zhí)行,在一般的應(yīng)用場(chǎng)合,,這種阻塞的訪問(wèn)方式是沒(méi)有問(wèn)題的,,但是當(dāng)程序需要進(jìn)行多次curl并發(fā)請(qǐng)求的時(shí)候,easy接口就無(wú)能為力了,,這個(gè)時(shí)候curl提供的multi接口就派上用場(chǎng)了,,網(wǎng)上關(guān)于libcurl的multi接口的使用資料比較少(百度出來(lái)的大部分都是php multi curl的資料),curl官網(wǎng)上貌似也只有相關(guān)函數(shù)的說(shuō)明,,有實(shí)際demo才能讓我們更快速的上手使用,,所以下面結(jié)合實(shí)際例子來(lái)講講multi curl接口的使用方法。

    相比而言,,multi接口的使用會(huì)比easy 接口稍微復(fù)雜點(diǎn),,畢竟multi接口是依賴easy接口的,首先粗略的講下其使用流程:curl_multi _init初始化一個(gè)multi curl對(duì)象,,為了同時(shí)進(jìn)行多個(gè)curl的并發(fā)訪問(wèn),,我們需要初始化多個(gè)easy curl對(duì)象,使用curl_easy_setopt進(jìn)行相關(guān)設(shè)置,,然后調(diào)用curl_multi _add_handle把easy curl對(duì)象添加到multi curl對(duì)象中,添加完畢后執(zhí)行curl_multi_perform方法進(jìn)行并發(fā)的訪問(wèn),,訪問(wèn)結(jié)束后curl_multi_remove_handle移除相關(guān)easy curl對(duì)象,,curl_easy_cleanup清除easy curl對(duì)象,最后curl_multi_cleanup清除multi curl對(duì)象,。

    上面的介紹只是給大家一個(gè)大概的印象,,實(shí)際使用中還有很多細(xì)節(jié)需要注意,好了,,代碼才能說(shuō)明一切,,下面的例子使用multi curl方式進(jìn)行多次http并發(fā)訪問(wèn),并輸出訪問(wèn)結(jié)果,。

  1. #include <string>  
  2. #include <iostream>  
  3.   
  4. #include <curl/curl.h>  
  5. #include <sys/time.h>  
  6. #include <unistd.h>  
  7.   
  8. using namespace std;  
  9.   
  10. size_t curl_writer(void *buffer, size_t size, size_t count, void * stream)  
  11. {  
  12.     std::string * pStream = static_cast<std::string *>(stream);  
  13.     (*pStream).append((char *)buffer, size * count);  
  14.   
  15.     return size * count;  
  16. };  
  17.   
  18. /** 
  19.  * 生成一個(gè)easy curl對(duì)象,,進(jìn)行一些簡(jiǎn)單的設(shè)置操作 
  20.  */  
  21. CURL * curl_easy_handler(const std::string & sUrl,  
  22.                          const std::string & sProxy,  
  23.                          std::string & sRsp,  
  24.                          unsigned int uiTimeout)  
  25. {  
  26.     CURL * curl = curl_easy_init();  
  27.   
  28.     curl_easy_setopt(curl, CURLOPT_URL, sUrl.c_str());  
  29.     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
  30.   
  31.     if (uiTimeout > 0)  
  32.     {  
  33.         curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, uiTimeout);  
  34.     }  
  35.     if (!sProxy.empty())  
  36.     {  
  37.         curl_easy_setopt(curl, CURLOPT_PROXY, sProxy.c_str());  
  38.     }  
  39.   
  40.     // write function //  
  41.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_writer);  
  42.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sRsp);  
  43.   
  44.     return curl;  
  45. }  
  46.   
  47. /** 
  48.  * 使用select函數(shù)監(jiān)聽(tīng)multi curl文件描述符的狀態(tài) 
  49.  * 監(jiān)聽(tīng)成功返回0,監(jiān)聽(tīng)失敗返回-1 
  50.  */  
  51. int curl_multi_select(CURLM * curl_m)  
  52. {  
  53.     int ret = 0;  
  54.   
  55.     struct timeval timeout_tv;  
  56.     fd_set  fd_read;  
  57.     fd_set  fd_write;  
  58.     fd_set  fd_except;  
  59.     int     max_fd = -1;  
  60.   
  61.     // 注意這里一定要清空f(shuō)dset,curl_multi_fdset不會(huì)執(zhí)行fdset的清空操作  //  
  62.     FD_ZERO(&fd_read);  
  63.     FD_ZERO(&fd_write);  
  64.     FD_ZERO(&fd_except);  
  65.   
  66.     // 設(shè)置select超時(shí)時(shí)間  //  
  67.     timeout_tv.tv_sec = 1;  
  68.     timeout_tv.tv_usec = 0;  
  69.   
  70.     // 獲取multi curl需要監(jiān)聽(tīng)的文件描述符集合 fd_set //  
  71.     curl_multi_fdset(curl_m, &fd_read, &fd_write, &fd_except, &max_fd);  
  72.   
  73.     /** 
  74.      * When max_fd returns with -1, 
  75.      * you need to wait a while and then proceed and call curl_multi_perform anyway. 
  76.      * How long to wait? I would suggest 100 milliseconds at least, 
  77.      * but you may want to test it out in your own particular conditions to find a suitable value. 
  78.      */  
  79.     if (-1 == max_fd)  
  80.     {  
  81.         return -1;  
  82.     }  
  83.   
  84.     /** 
  85.      * 執(zhí)行監(jiān)聽(tīng),,當(dāng)文件描述符狀態(tài)發(fā)生改變的時(shí)候返回 
  86.      * 返回0,,程序調(diào)用curl_multi_perform通知curl執(zhí)行相應(yīng)操作 
  87.      * 返回-1,表示select錯(cuò)誤 
  88.      * 注意:即使select超時(shí)也需要返回0,,具體可以去官網(wǎng)看文檔說(shuō)明 
  89.      */  
  90.     int ret_code = ::select(max_fd + 1, &fd_read, &fd_write, &fd_except, &timeout_tv);  
  91.     switch(ret_code)  
  92.     {  
  93.     case -1:  
  94.         /* select error */  
  95.         ret = -1;  
  96.         break;  
  97.     case 0:  
  98.         /* select timeout */  
  99.     default:  
  100.         /* one or more of curl's file descriptors say there's data to read or write*/  
  101.         ret = 0;  
  102.         break;  
  103.     }  
  104.   
  105.     return ret;  
  106. }  
  107.   
  108. #define MULTI_CURL_NUM 3  
  109.   
  110. // 這里設(shè)置你需要訪問(wèn)的url //  
  111. std::string     URL     = "http://";  
  112. // 這里設(shè)置代理ip和端口  //  
  113. std::string     PROXY   = "ip:port";  
  114. // 這里設(shè)置超時(shí)時(shí)間  //  
  115. unsigned int    TIMEOUT = 2000; /* ms */  
  116.   
  117. /** 
  118.  * multi curl使用demo 
  119.  */  
  120. int curl_multi_demo(int num)  
  121. {  
  122.     // 初始化一個(gè)multi curl 對(duì)象 //  
  123.     CURLM * curl_m = curl_multi_init();  
  124.   
  125.     std::string     RspArray[num];  
  126.     CURL *          CurlArray[num];  
  127.   
  128.     // 設(shè)置easy curl對(duì)象并添加到multi curl對(duì)象中  //  
  129.     for (int idx = 0; idx < num; ++idx)  
  130.     {  
  131.         CurlArray[idx] = NULL;  
  132.         CurlArray[idx] = curl_easy_handler(URL, PROXY, RspArray[idx], TIMEOUT);  
  133.         if (CurlArray[idx] == NULL)  
  134.         {  
  135.             return -1;  
  136.         }  
  137.         curl_multi_add_handle(curl_m, CurlArray[idx]);  
  138.     }  
  139.   
  140.     /* 
  141.      * 調(diào)用curl_multi_perform函數(shù)執(zhí)行curl請(qǐng)求 
  142.      * url_multi_perform返回CURLM_CALL_MULTI_PERFORM時(shí),,表示需要繼續(xù)調(diào)用該函數(shù)直到返回值不是CURLM_CALL_MULTI_PERFORM為止 
  143.      * running_handles變量返回正在處理的easy curl數(shù)量,,running_handles為0表示當(dāng)前沒(méi)有正在執(zhí)行的curl請(qǐng)求 
  144.      */  
  145.     int running_handles;  
  146.     while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles))  
  147.     {  
  148.         cout << running_handles << endl;  
  149.     }  
  150.   
  151.     /** 
  152.      * 為了避免循環(huán)調(diào)用curl_multi_perform產(chǎn)生的cpu持續(xù)占用的問(wèn)題,采用select來(lái)監(jiān)聽(tīng)文件描述符 
  153.      */  
  154.     while (running_handles)  
  155.     {  
  156.         if (-1 == curl_multi_select(curl_m))  
  157.         {  
  158.             cerr << "select error" << endl;  
  159.             break;  
  160.         } else {  
  161.             // select監(jiān)聽(tīng)到事件,,調(diào)用curl_multi_perform通知curl執(zhí)行相應(yīng)的操作 //  
  162.             while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles))  
  163.             {  
  164.                 cout << "select: " << running_handles << endl;  
  165.             }  
  166.         }  
  167.         cout << "select: " << running_handles << endl;  
  168.     }  
  169.   
  170.     // 輸出執(zhí)行結(jié)果 //  
  171.     int         msgs_left;  
  172.     CURLMsg *   msg;  
  173.     while((msg = curl_multi_info_read(curl_m, &msgs_left)))  
  174.     {  
  175.         if (CURLMSG_DONE == msg->msg)  
  176.         {  
  177.             int idx;  
  178.             for (idx = 0; idx < num; ++idx)  
  179.             {  
  180.                 if (msg->easy_handle == CurlArray[idx]) break;  
  181.             }  
  182.   
  183.             if (idx == num)  
  184.             {  
  185.                 cerr << "curl not found" << endl;  
  186.             } else  
  187.             {  
  188.                 cout << "curl [" << idx << "] completed with status: "  
  189.                         << msg->data.result << endl;  
  190.                 cout << "rsp: " << RspArray[idx] << endl;  
  191.             }  
  192.         }  
  193.     }  
  194.   
  195.     // 這里要注意cleanup的順序 //  
  196.     for (int idx = 0; idx < num; ++idx)  
  197.     {  
  198.         curl_multi_remove_handle(curl_m, CurlArray[idx]);  
  199.     }  
  200.   
  201.     for (int idx = 0; idx < num; ++idx)  
  202.     {  
  203.         curl_easy_cleanup(CurlArray[idx]);  
  204.     }  
  205.   
  206.     curl_multi_cleanup(curl_m);  
  207.   
  208.     return 0;  
  209. }  
  210.   
  211. /** 
  212.  * easy curl使用demo 
  213.  */  
  214. int curl_easy_demo(int num)  
  215. {  
  216.     std::string     RspArray[num];  
  217.   
  218.     for (int idx = 0; idx < num; ++idx)  
  219.     {  
  220.         CURL * curl = curl_easy_handler(URL, PROXY, RspArray[idx], TIMEOUT);  
  221.         CURLcode code = curl_easy_perform(curl);  
  222.         cout << "curl [" << idx << "] completed with status: "  
  223.                 << code << endl;  
  224.         cout << "rsp: " << RspArray[idx] << endl;  
  225.   
  226.         // clear handle //  
  227.         curl_easy_cleanup(curl);  
  228.     }  
  229.   
  230.     return 0;  
  231. }  
  232.   
  233. #define USE_MULTI_CURL  
  234.   
  235. struct timeval begin_tv, end_tv;  
  236.   
  237. int main(int argc, char * argv[])  
  238. {  
  239.     if (argc < 2)  
  240.     {  
  241.         return -1;  
  242.     }  
  243.     int num = atoi(argv[1]);  
  244.   
  245.     // 獲取開(kāi)始時(shí)間 //  
  246.     gettimeofday(&begin_tv, NULL);  
  247. #ifdef USE_MULTI_CURL  
  248.     // 使用multi接口進(jìn)行訪問(wèn) //  
  249.     curl_multi_demo(num);  
  250. #else  
  251.     // 使用easy接口進(jìn)行訪問(wèn) //  
  252.     curl_easy_demo(num);  
  253. #endif  
  254.     // 獲取結(jié)束時(shí)間  //  
  255.     struct timeval end_tv;  
  256.     gettimeofday(&end_tv, NULL);  
  257.   
  258.     // 計(jì)算執(zhí)行延時(shí)并輸出,,用于比較  //  
  259.     int eclapsed = (end_tv.tv_sec - begin_tv.tv_sec) * 1000 +  
  260.                    (end_tv.tv_usec - begin_tv.tv_usec) / 1000;  
  261.   
  262.     cout << "eclapsed time:" << eclapsed << "ms" << endl;  
  263.   
  264.     return 0;  
  265. }  


    上面的代碼在關(guān)鍵位置都做了詳細(xì)的注釋,相信應(yīng)該不難看懂,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多