zoukankan      html  css  js  c++  java
  • libcurl异步访问示例

    libcurl异步访问示例

    用同步阻塞的方式跑单线程效率太低,每次开新线程去跑curl太浪费资源,没有必要。
    有没有办法用IO复用的方式跑单线程?libcurl自带的curl_multi_wait(封装了IO复用)可以完成这个工作。

    参考地址:

    https://www.cnblogs.com/heluan/p/10177475.html
    https://blog.csdn.net/whui19890911/article/details/79320408
    https://www.cnblogs.com/bugutian/p/4868167.html
    https://www.cnblogs.com/dvss/archive/2013/04/11/3014699.html
    

    代码示例:

    #include <iostream>
    #include <thread>
    #include <string>
    #include <mutex>
    #include <list>
    #include <map>
    #include <curl/multi.h>
    #include <curl/curl.h>
    #include <curl/easy.h>
    
    using namespace std;
    
    typedef unsigned long long UInt64;
    
    std::mutex msgListMtx;
    std::list<int>  msgList;
      
    // 这里设置你需要访问的url //  
    std::string     BASE_URL = "http://192.168.1.135:19090/vinput?key=";  
    // 这里设置代理ip和端口  //  
    std::string     PROXY   = "";
    // 这里设置超时时间  //  
    unsigned int    TIMEOUT = 2000; /* ms */  
    unsigned int    globalCnt = 0;
    
    typedef struct SReqNode{
        std::string url;
        std::string respData;
        unsigned int seq;
        SReqNode()
        {
            seq = 0;
            url = "";
            respData = "";
        }
    } SReqNode;
    
    size_t curl_writer(void *buffer, size_t size, size_t count, void * stream)  
    {
        std::string * pStream = static_cast<std::string *>(stream);  
        (*pStream).append((char *)buffer, size * count);  
      
        return size * count;  
    };  
      
    /** 
     * 生成一个easy curl对象,进行一些简单的设置操作 
     */  
    CURL * curl_easy_handler(const std::string & sUrl,  
                             const std::string & sProxy,  
                             std::string & sRsp,  
                             unsigned int uiTimeout)  
    {  
        CURL * curl = curl_easy_init();  
      
        curl_easy_setopt(curl, CURLOPT_URL, sUrl.c_str());  
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
      
        if (uiTimeout > 0)  
        {  
            curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, uiTimeout);  
        }  
        if (!sProxy.empty())  
        {  
            curl_easy_setopt(curl, CURLOPT_PROXY, sProxy.c_str());  
        }  
      
        // write function //  
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_writer);  
        //curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_writer);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sRsp);  
      
        return curl;  
    }  
    void dealMsg(SReqNode* reqNodePtr,int status)
    {
        cout << "curl [" << reqNodePtr->seq << "] status: " 
                << status << ",says: "
                << reqNodePtr->respData << endl; 
    }
    
    void dealErr()
    {
        cout << "Response Msg is not found." << endl; 
    }
    
    int key_send_thread()
    {
        // 初始化一个multi curl 对象 //  
        CURLM * curl_m = curl_multi_init();
        std::map<UInt64,SReqNode*>  handle2rsp;
    
        while (1)  
        {
            std::list<int> tmpKeys;
            msgListMtx.lock();
            tmpKeys.swap(msgList);
            msgListMtx.unlock();
            //cout << "SIZE:" << tmpKeys.size() << endl;
            std::list<int>::iterator iter = tmpKeys.begin();
            for (;iter != tmpKeys.end();iter ++)
            {
                CURL* tmpHandler = NULL;
                std::string tmpUrl = BASE_URL + std::to_string(*iter) + "&";
                SReqNode* tmpReqNode = new SReqNode();
                tmpReqNode->seq = globalCnt++;
                tmpReqNode->url = tmpUrl;
                tmpHandler = curl_easy_handler(tmpUrl, PROXY, tmpReqNode->respData, TIMEOUT); 
                if (tmpHandler == NULL)  
                {
                    continue;
                }
                handle2rsp[(UInt64)tmpHandler] = tmpReqNode;
                curl_multi_add_handle(curl_m, tmpHandler);  
            }
            
            /* 
             * 调用curl_multi_perform函数执行curl请求 
             * url_multi_perform返回CURLM_CALL_MULTI_PERFORM时,表示需要继续调用该函数, 直到返回值不是CURLM_CALL_MULTI_PERFORM为止 
             * running_handles变量返回正在处理的easy curl数量,running_handles为0表示当前没有正在执行的curl请求 
             */  
            int runningHandles;  
            while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &runningHandles))
            {
                cout << runningHandles << endl;  
            }
            int numfds,msgs_left,res;
            res = curl_multi_wait(curl_m, NULL, 0, 200, &numfds);
            CURLMsg *   msg;  
            while((msg = curl_multi_info_read(curl_m, &msgs_left)))
            {
                cout << "while curl_multi_info_read:"  << endl;
                if (CURLMSG_DONE == msg->msg)  
                {
                    int idx;  
                    std::map<UInt64, SReqNode*>::iterator iter2 = handle2rsp.find(UInt64(msg->easy_handle));
                    if (iter2 != handle2rsp.end())
                    {
                        dealMsg(iter2->second, msg->data.result);
                        SReqNode* tmpPrt = iter2->second;
                        handle2rsp.erase(iter2);
                        curl_multi_remove_handle(curl_m, msg->easy_handle);
                        curl_easy_cleanup( msg->easy_handle);
                        delete tmpPrt;
                    }else{
                        dealErr();
                    } 
                }
            }
        }
        curl_multi_cleanup(curl_m);  
      
        return 0;  
    }
    
    int main()
    {
        thread senderThread(key_send_thread);
        int input;
        while(1)
        {
            cout << "input:";
            cin >> input;
            if (input == 3306)
            {
                break;
            }
            msgListMtx.lock();
            msgList.push_back(input);
            msgListMtx.unlock();
        }
        
        senderThread.join();
        return 0;
    }
    
    /********************
    ### 编译
    g++ testcurl.cpp -I/usr/local/sdk/include -I/usr/local/sdk/include/curl -lidn -lrt -lcrypto -lssl -lz  -lpthread /usr/local/sdk/lib/libcurl.a -std=c++11 -o testurl
    
    ### 运行
    [root@lh]# ./testurl 
    input:
    654
    input:while curl_multi_info_read:
    curl [0] status: 0,says: Recv:654
    6546
    input:while curl_multi_info_read:
    curl [1] status: 0,says: Recv:6546
    46
    *********************/
    
    转载请注明来源:https://www.cnblogs.com/bugutian/
  • 相关阅读:
    10. 正则表达式匹配
    svn 类似.gitignore功能实现
    GF学习未解之谜
    cocos
    unity 编辑器内对Game视图进行截图
    Roughlike游戏里面的随机数种子
    网站推荐——游戏图标网
    Unity 使用image绘制线段 直线
    c# unity 异步任务队列
    Unity编辑器调用外部exe程序 和 windows文件夹
  • 原文地址:https://www.cnblogs.com/bugutian/p/15319129.html
Copyright © 2011-2022 走看看