博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HttpClient(联网)
阅读量:6940 次
发布时间:2019-06-27

本文共 18020 字,大约阅读时间需要 60 分钟。

抽样:

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
的位置。

        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使用

#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

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

你可能感兴趣的文章
统计--VARCHAR与NVARCHAR在统计预估上的区别
查看>>
SQL Tuning 基础概述05 - Oracle 索引类型及介绍
查看>>
Sql Server系列:流程控制语句
查看>>
转:windows API 函数大全
查看>>
File中操作路径的API(转)
查看>>
[AngularJS] Using $anchorScroll
查看>>
Centos 6.4 安装erlang&rabbitmq
查看>>
C语言的数组初始化
查看>>
rtesseract的例子
查看>>
[Papers]NSE, $\p_3u$, Lebesgue space [Penel-Pokorny, AM, 2004]
查看>>
同样的so,放到不同的project中,就会报错
查看>>
mysql 锁
查看>>
android动画-动画分类及代码演示样例
查看>>
Java中的锁(转)
查看>>
Codeforces Round #288 (Div. 2) E. Arthur and Brackets 贪心
查看>>
用cocos2d-x 3.2 实现的FlappyBird
查看>>
http://jadethao.iteye.com/blog/1926525
查看>>
菜鸟要做架构师(三)——单元测试的七种境界
查看>>
Replication的犄角旮旯(七)-- 一个DDL引发的血案(下)(聊聊logreader的延迟)
查看>>
类在编写过程中的一些注意事项
查看>>