• HttpClient(联网)


    抽样:

    void GameRequest::initRequset(const char* url, cocos2d::CCObject* pTarget, cocos2d::SEL_CallFuncND pSelector)

    {

        cocos2d::extension::CCHttpRequest* request = new cocos2d::extension::CCHttpRequest();

        request->setUrl(url);

        //设置为GET请求:kHttpGet

        request->setRequestType(cocos2d::extension::CCHttpRequest::kHttpGet);

        //设置处理响应回调函数

        if(pTarget != NULL && pSelector != NULL){

            request->setResponseCallback(pTarget, pSelector);

        }

        cocos2d::extension::CCHttpClient::getInstance()->setTimeoutForConnect(15);

        cocos2d::extension::CCHttpClient::getInstance()->setTimeoutForRead(15);

        cocos2d::extension::CCHttpClient::getInstance()->send(request);

        int countme = request->retainCount();

        if(countme <= 0)

        {

            CCLOG("=request retaincount==================%d",request->retainCount());

        }    

        request->release();

    }


    void CoverScene::checkUserNameRequestCallBack(cocos2d::CCNode *sender, void *data)

    {

        cocos2d::extension::CCHttpResponse *response = (cocos2d::extension::CCHttpResponse*)data;

        if (!response)

        {

            return;

        }

        //你能够使用: response->request->reqType获取请求类型

        if (0 != strlen(response->getHttpRequest()->getTag()))

        {

            CCLog("%s completed", response->getHttpRequest()->getTag());

        }

        //获取状态码

        int statusCode = response->getResponseCode();

        char statusString[64] = {};

        sprintf(statusString, "HTTP Status Code: %d, tag = %s", statusCode, response->getHttpRequest()->getTag());

        CCLog("response code: %d", statusCode);

        

        if (!response->isSucceed())

        {

            //訪问失败获取错误信息

            CCLog("response failed");

            CCLog("error buffer: %s", response->getErrorBuffer());

            return;

        }

        try {

    vector::data

    指针到 vector 类 的第一个元素成功或为空 vector的位置。

            std::vector<char> *buffer = response->getResponseData();

            std::string str = std::string(buffer->data(), buffer->size());

            

            Json *dataJson = Json_create(str.data());

            std::cout<<Json_getSize(dataJson)<<std::endl;

            MessageBoxLayer::getMessageBoxPoint()->callMessageBoxRemove();

            if (Json_getSize(dataJson) == 1)

            {

                //账号password错误

                CCLOG("账号password错误.........");

                changeToLogin();

            }

            else

            {

                Json *infoDataJson = Json_getItem(dataJson, "data");

                m_accessToken = Json_getItem(infoDataJson,"token")->valuestring;

                GameUser::GetGameUser()->uninqueId = atoll(Json_getItemAt(Json_getItemAt(dataJson, 1),0)->valuestring);

                GameUser::GetGameUser()->platform_user_id = Json_getString(infoDataJson, "platform_user_id", "");//Json_String(infoDataJson, "platform_user_id");

                CoverScene::m_iType = 0;

                getServerListRequest();

            }

        }

        catch (const std::exception& rhs)

        {

            CCLOG("数据异常");

        }

    }


    #ifndef __CCHTTPREQUEST_H__

    #define __CCHTTPREQUEST_H__


    #include "cocos2d.h"

    #include "ExtensionMacros.h"


    #include "HttpRequest.h"

    #include "HttpResponse.h"


    NS_CC_EXT_BEGIN


    /**

     * @addtogroup Network

     * @{

     */



    /** @brief Singleton that handles(操控) asynchronous(asyn 异步 chromous 同步) http requests

     * Once the request completed, a callback will issued(公布) in main thread when it provided during make request

     */

    class CCHttpClient : public CCObject

    {

    public:

        /** Return the shared instance **/

        static CCHttpClient *getInstance();// CCHttpClient 是一个单例类

        

        /** Relase the shared instance **/

        static voiddestroyInstance();    

    {

        CCAssert(s_pHttpClient, "");

        CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCHttpClient::dispatchResponseCallbacks), s_pHttpClient);

        s_pHttpClient->release();

    }

     

        /**

         * Add a get request to task queue

         * @param request a CCHttpRequest object, which includes url, response callback etc.

                          please make sure request->_requestData is clear before calling "send" here.

         * @return NULL

         */

        voidsend(CCHttpRequest* request);//这个用的最多 CCHttpRequest 增加请求列表  

      

        

        /**

         * Change the connect timeout

         * @param timeout 

         * @return NULL

         */

        inline voidsetTimeoutForConnect(int value) {_timeoutForConnect = value;};//设置连接超时 时间值

        

        /**

         * Get connect timeout

         * @return int

         *

         */

        inline int getTimeoutForConnect() {return _timeoutForConnect;}//获得连接时间

        

        

        /**

         * Change the download timeout

         * @param value

         * @return NULL

         */

        inline voidsetTimeoutForRead(int value) {_timeoutForRead = value;};

        


        /**

         * Get download timeout

         * @return int

         */

        inline intgetTimeoutForRead() {return _timeoutForRead;};

            

    private:

        CCHttpClient();//单例类

    : _timeoutForConnect(30)

    , _timeoutForRead(60)

    {

        CCDirector::sharedDirector()->getScheduler()->scheduleSelector(

                        schedule_selector(CCHttpClient::dispatchResponseCallbacks), this, 0, false);

        CCDirector::sharedDirector()->getScheduler()->pauseTarget(this);

    }


        virtual ~CCHttpClient();  

    //当类是在栈上 类在离开作用域时会调用析构函数释放空间,此时无法调用私有的析构函数

    //假设在堆上分配空间,仅仅有在delete时才会调用析构函数

    ////////////////////////析构函数私有

    当我们规定类仅仅能在堆上分配内存时,就能够将析构函数声明为私有的。

    class alloc

    {

    public:

        alloc():

    private:

       ~alloc();

    };

     

    假设在栈上分配空间。类在离开作用域时会调用析构函数释放空间,此时无法调用私有的析构函数。

    假设在堆上分配空间。仅仅有在delete时才会调用析构函数。

     

    能够加入一个destroy()函数来释放,从而解决不能在析构函数中加入delete的问题。

    class alloc

    {

    public:

        alloc():

     destroy(){ delete this;}  

    private:

       ~alloc();

    };

    /////////////////////////////////////////////////////


        bool init(void);

        

        /**

         * Init pthread mutex, semaphore, and create new thread for http requests

         * @return bool

         */

        boollazyInitThreadSemphore(); // 私有函数 无需深究   用到了很多额外函数 cpp里写的

    {

        if (s_requestQueue != NULL) {

            return true;

        } else {

            

            s_requestQueue = new CCArray();

            s_requestQueue->init();

            

            s_responseQueue = new CCArray();

            s_responseQueue->init();

            

            pthread_mutex_init(&s_requestQueueMutex, NULL);

            pthread_mutex_init(&s_responseQueueMutex, NULL);

            

            pthread_mutex_init(&s_SleepMutex, NULL);

            pthread_cond_init(&s_SleepCondition, NULL);


            pthread_create(&s_networkThread, NULL, networkThread, NULL);

            pthread_detach(s_networkThread);

            

            need_quit = false;

        }

        

        return true;

    }


       //Poll function called from main thread to dispatch callbacks when http requests finished 

       // Poll and notify main thread if responses exists in queue

        voiddispatchResponseCallbacks(float delta);  // 分发网络回应  私有函数 无需深究

        

    private:

        int _timeoutForConnect;

        int _timeoutForRead;

        

        // std::string reqId;

    };


    // end of Network group

    /// @}


    NS_CC_EXT_END


    #endif //__CCHTTPREQUEST_H__



    .cpp

             作用域 生存期 static extern..........         

    以下的 static修饰的函数 生存期全局 作用域内部 外部无法通过extern使用


    #include "HttpClient.h"

    // #include "platform/CCThread.h"


    #include <queue>

    #include <pthread.h>

    #include <errno.h>


    #include "curl/curl.h"


    NS_CC_EXT_BEGIN


    static pthread_t        s_networkThread;

    static pthread_mutex_t  s_requestQueueMutex;

    static pthread_mutex_t  s_responseQueueMutex;


    static pthread_mutex_ts_SleepMutex;

    static pthread_cond_ts_SleepCondition;


    static unsigned long    s_asyncRequestCount = 0;


    #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)

    typedef int int32_t;

    #endif


    static bool need_quit = false;


    static CCArray* s_requestQueue = NULL;

    static CCArray* s_responseQueue = NULL;


    static CCHttpClient *s_pHttpClient = NULL; // pointer to singleton


    static char s_errorBuffer[CURL_ERROR_SIZE];


    typedef size_t (*write_callback)(void *ptr, size_t size, size_t nmemb, void *stream);


    // Callback function used by libcurl for collect response data

    static size_t writeData(void *ptr, size_t size, size_t nmemb, void *stream)

    {

        std::vector<char> *recvBuffer = (std::vector<char>*)stream;

        size_t sizes = size * nmemb;

        

        // add data to the end of recvBuffer

        // write data maybe called more than once in a single request

        recvBuffer->insert(recvBuffer->end(), (char*)ptr, (char*)ptr+sizes);

        

        return sizes;

    }


    // Callback function used by libcurl for collect header data

    static size_t writeHeaderData(void *ptr, size_t size, size_t nmemb, void *stream)

    {

        std::vector<char> *recvBuffer = (std::vector<char>*)stream;

        size_t sizes = size * nmemb;

        

        // add data to the end of recvBuffer

        // write data maybe called more than once in a single request

        recvBuffer->insert(recvBuffer->end(), (char*)ptr, (char*)ptr+sizes);

        

        return sizes;

    }



    static int processGetTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

    static int processPostTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

    static int processPutTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

    static int processDeleteTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

    // int processDownloadTask(HttpRequest *task, write_callback callback, void *stream, int32_t *errorCode);



    // Worker thread

    static void* networkThread(void *data)

    {    

        CCHttpRequest *request = NULL;

        

        while (true) 

        {

            if (need_quit)

            {

                break;

            }

            

            // step 1: send http request if the requestQueue isn't empty

            request = NULL;

            

            pthread_mutex_lock(&s_requestQueueMutex); //Get request task from queue

            if (0 != s_requestQueue->count())

            {

                request = dynamic_cast<CCHttpRequest*>(s_requestQueue->objectAtIndex(0));

                s_requestQueue->removeObjectAtIndex(0);  

                // request's refcount = 1 here

            }

            pthread_mutex_unlock(&s_requestQueueMutex);

            

            if (NULL == request)

            {

           // Wait for http request tasks from main thread

           pthread_cond_wait(&s_SleepCondition, &s_SleepMutex);

                continue;

            }

            

            // step 2: libcurl sync access

            

            // Create a HttpResponse object, the default setting is http access failed

            CCHttpResponse *response = new CCHttpResponse(request);

            

            // request's refcount = 2 here, it's retained by HttpRespose constructor

            request->release();

            // ok, refcount = 1 now, only HttpResponse hold it.

            

            int32_t responseCode = -1;

            int retValue = 0;


            // Process the request -> get response packet

            switch (request->getRequestType())

            {

                case CCHttpRequest::kHttpGet: // HTTP GET

                    retValue = processGetTask(request,

                                              writeData, 

                                              response->getResponseData(), 

                                              &responseCode,

                                              writeHeaderData,

                                              response->getResponseHeader());

                    break;

                

                case CCHttpRequest::kHttpPost: // HTTP POST

                    retValue = processPostTask(request,

                                               writeData, 

                                               response->getResponseData(), 

                                               &responseCode,

                                               writeHeaderData,

                                               response->getResponseHeader());

                    break;


                case CCHttpRequest::kHttpPut:

                    retValue = processPutTask(request,

                                              writeData,

                                              response->getResponseData(),

                                              &responseCode,

                                              writeHeaderData,

                                              response->getResponseHeader());

                    break;


                case CCHttpRequest::kHttpDelete:

                    retValue = processDeleteTask(request,

                                                 writeData,

                                                 response->getResponseData(),

                                                 &responseCode,

                                                 writeHeaderData,

                                                 response->getResponseHeader());

                    break;

                

                default:

                    CCAssert(true, "CCHttpClient: unkown request type, only GET and POSt are supported");

                    break;

            }

                    

            // write data to HttpResponse

            response->setResponseCode(responseCode);

            

            if (retValue != 0) 

            {

                response->setSucceed(false);

                response->setErrorBuffer(s_errorBuffer);

            }

            else

            {

                response->setSucceed(true);

            }


            

            // add response packet into queue

            pthread_mutex_lock(&s_responseQueueMutex);

            s_responseQueue->addObject(response);

            pthread_mutex_unlock(&s_responseQueueMutex);

            

            // resume dispatcher selector

            CCDirector::sharedDirector()->getScheduler()->resumeTarget(CCHttpClient::getInstance());

        }

        

        // cleanup: if worker thread received quit signal, clean up un-completed request queue

        pthread_mutex_lock(&s_requestQueueMutex);

        s_requestQueue->removeAllObjects();

        pthread_mutex_unlock(&s_requestQueueMutex);

        s_asyncRequestCount -= s_requestQueue->count();

        

        if (s_requestQueue != NULL) {

            

            pthread_mutex_destroy(&s_requestQueueMutex);

            pthread_mutex_destroy(&s_responseQueueMutex);

            

            pthread_mutex_destroy(&s_SleepMutex);

            pthread_cond_destroy(&s_SleepCondition);


            s_requestQueue->release();

            s_requestQueue = NULL;

            s_responseQueue->release();

            s_responseQueue = NULL;

        }


        pthread_exit(NULL);

        

        return 0;

    }


    //Configure curl's timeout property

    static bool configureCURL(CURL *handle)

    {

        if (!handle) {

            return false;

        }

        

        int32_t code;

        code = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, s_errorBuffer);

        if (code != CURLE_OK) {

            return false;

        }

        code = curl_easy_setopt(handle, CURLOPT_TIMEOUT, CCHttpClient::getInstance()->getTimeoutForRead());

        if (code != CURLE_OK) {

            return false;

        }

        code = curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, CCHttpClient::getInstance()->getTimeoutForConnect());

        if (code != CURLE_OK) {

            return false;

        }

        curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);

        curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L);


        return true;

    }


    class CURLRaii

    {

        /// Instance of CURL

        CURL *m_curl;

        /// Keeps custom header data

        curl_slist *m_headers;

    public:

        CURLRaii()

            : m_curl(curl_easy_init())

            , m_headers(NULL)

        {

        }


        ~CURLRaii()

        {

            if (m_curl)

                curl_easy_cleanup(m_curl);

            /* free the linked list for header data */

            if (m_headers)

                curl_slist_free_all(m_headers);

        }


        template <class T>

        bool setOption(CURLoption option, T data)

        {

            return CURLE_OK == curl_easy_setopt(m_curl, option, data);

        }


        /**

         * @brief Inits CURL instance for common usage

         * @param request Null not allowed

         * @param callback Response write callback

         * @param stream Response write stream

         */

        bool init(CCHttpRequest *request, write_callback callback, void *stream, write_callback headerCallback, void *headerStream)

        {

            if (!m_curl)

                return false;

            if (!configureCURL(m_curl))

                return false;


            /* get custom header data (if set) */

          std::vector<std::string> headers=request->getHeaders();

            if(!headers.empty())

            {

                /* append custom headers one by one */

                for (std::vector<std::string>::iterator it = headers.begin(); it != headers.end(); ++it)

                    m_headers = curl_slist_append(m_headers,it->c_str());

                /* set custom headers for curl */

                if (!setOption(CURLOPT_HTTPHEADER, m_headers))

                    return false;

            }


            return setOption(CURLOPT_URL, request->getUrl())

                    && setOption(CURLOPT_WRITEFUNCTION, callback)

                    && setOption(CURLOPT_WRITEDATA, stream)

                    && setOption(CURLOPT_HEADERFUNCTION, headerCallback)

                    && setOption(CURLOPT_HEADERDATA, headerStream);

            

        }


        /// @param responseCode Null not allowed

        bool perform(int *responseCode)

        {

            if (CURLE_OK != curl_easy_perform(m_curl))

                return false;

            CURLcode code = curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, responseCode);

            if (code != CURLE_OK || *responseCode != 200)

                return false;

            

            // Get some mor data.

            

            return true;

        }

    };


    //Process Get Request

    static int processGetTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

    {

        CURLRaii curl;

        bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

                && curl.setOption(CURLOPT_FOLLOWLOCATION, true)

                && curl.perform(responseCode);

        return ok ?

    0 : 1;

    }


    //Process POST Request

    static int processPostTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

    {

        CURLRaii curl;

        bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

                && curl.setOption(CURLOPT_POST, 1)

                && curl.setOption(CURLOPT_POSTFIELDS, request->getRequestData())

                && curl.setOption(CURLOPT_POSTFIELDSIZE, request->getRequestDataSize())

                && curl.perform(responseCode);

        return ok ? 0 : 1;

    }


    //Process PUT Request

    static int processPutTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

    {

        CURLRaii curl;

        bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

                && curl.setOption(CURLOPT_CUSTOMREQUEST, "PUT")

                && curl.setOption(CURLOPT_POSTFIELDS, request->getRequestData())

                && curl.setOption(CURLOPT_POSTFIELDSIZE, request->getRequestDataSize())

                && curl.perform(responseCode);

        return ok ?

    0 : 1;

    }


    //Process DELETE Request

    static int processDeleteTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

    {

        CURLRaii curl;

        bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

                && curl.setOption(CURLOPT_CUSTOMREQUEST, "DELETE")

                && curl.setOption(CURLOPT_FOLLOWLOCATION, true)

                && curl.perform(responseCode);

        return ok ? 0 : 1;

    }


    // HttpClient implementation

    CCHttpClient* CCHttpClient::getInstance()

    {

        if (s_pHttpClient == NULL) {

            s_pHttpClient = new CCHttpClient();

        }

        

        return s_pHttpClient;

    }


    void CCHttpClient::destroyInstance()

    {

        CCAssert(s_pHttpClient, "");

        CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCHttpClient::dispatchResponseCallbacks), s_pHttpClient);

        s_pHttpClient->release();

    }


    CCHttpClient::CCHttpClient()

    : _timeoutForConnect(30)

    , _timeoutForRead(60)

    {

        CCDirector::sharedDirector()->getScheduler()->scheduleSelector(

                        schedule_selector(CCHttpClient::dispatchResponseCallbacks), this, 0, false);

        CCDirector::sharedDirector()->getScheduler()->pauseTarget(this);

    }


    CCHttpClient::~CCHttpClient()

    {

        need_quit = true;

        

        if (s_requestQueue != NULL) {

       pthread_cond_signal(&s_SleepCondition);

        }

        

        s_pHttpClient = NULL;

    }


    //Lazy create semaphore & mutex & thread

    bool CCHttpClient::lazyInitThreadSemphore()

    {

        if (s_requestQueue != NULL) {

            return true;

        } else {

            

            s_requestQueue = new CCArray();

            s_requestQueue->init();

            

            s_responseQueue = new CCArray();

            s_responseQueue->init();

            

            pthread_mutex_init(&s_requestQueueMutex, NULL);

            pthread_mutex_init(&s_responseQueueMutex, NULL);

            

            pthread_mutex_init(&s_SleepMutex, NULL);

            pthread_cond_init(&s_SleepCondition, NULL);


            pthread_create(&s_networkThread, NULL, networkThread, NULL);

            pthread_detach(s_networkThread);

            

            need_quit = false;

        }

        

        return true;

    }


    //Add a get task to queue

    void CCHttpClient::send(CCHttpRequest* request)

    {    

        if (false == lazyInitThreadSemphore()) 

        {

            return;

        }

        

        if (!request)

        {

            return;

        }

            

        ++s_asyncRequestCount;

        

        request->retain();

            

        pthread_mutex_lock(&s_requestQueueMutex);

        s_requestQueue->addObject(request);

        pthread_mutex_unlock(&s_requestQueueMutex);

        

        // Notify thread start to work

        pthread_cond_signal(&s_SleepCondition);

    }


    // Poll and notify main thread if responses exists in queue

    void CCHttpClient::dispatchResponseCallbacks(float delta)

    {

        // CCLog("CCHttpClient::dispatchResponseCallbacks is running");

        

        CCHttpResponse* response = NULL;

        

        pthread_mutex_lock(&s_responseQueueMutex);

        if (s_responseQueue->count())

        {

            response = dynamic_cast<CCHttpResponse*>(s_responseQueue->objectAtIndex(0));

            s_responseQueue->removeObjectAtIndex(0);

        }

        pthread_mutex_unlock(&s_responseQueueMutex);

        

        if (response)

        {

            --s_asyncRequestCount;

            

            CCHttpRequest *request = response->getHttpRequest();

            CCObject *pTarget = request->getTarget();

            SEL_HttpResponse pSelector = request->getSelector();


            if (pTarget && pSelector) 

            {

                (pTarget->*pSelector)(this, response);

            }

            

            response->release();

        }

        

        if (0 == s_asyncRequestCount) 

        {

            CCDirector::sharedDirector()->getScheduler()->pauseTarget(this);

        }

        

    }


    NS_CC_EXT_END












    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    让你少奋斗10年的工作经验
    POJ Exponentiation解题
    数据结构树和二叉树
    语句摘录
    ACM解题报告格式
    编程规范
    数据结构图
    Java学习之二Java反射机制
    使用Python正则表达式提取搜索结果中的站点
    toj 1702 A Knight's Journey
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4900868.html
Copyright © 2020-2023  润新知