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)

        {

            //账号密码错误

            CCLOG("账号密码错误.........");

            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












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值