• coco2dx c++ HTTP实现


    coco2dx c++ HTTP实现 

    达到的结果如下面的

    iPhone截图

    android 日志截图

    流程图例如以下

    功能主要通过CURL c pthread 实现 我实现的不是多线程断点(假设要实现能够依据我这个进行加入任务序列,可參考 cocos2d-x 中AssetsManager的实现,事实上我的部分也是參考这个写的 为什么写这个呢 原因就是 AssetsManager是不支持断点续传的)

    博客地址:http://blog.csdn.net/vpingchangxin/article/details/22309067

    详细能够去CURL官网或者找资料科普一下

    PS:假设是版本号公布最后设置超时时间20秒左右否则下载会占用很多其它下载实现效率等问题 我是为了測试 设置超时时间为2秒

    1.先创建一个界面进行控制进行下载、停止、删除、进度 并绑定事件

    2.在进行下载中开一个线程进行下载 (由于牵涉到UI,不开线程UI会卡着阻塞UI线程直到下载完毕)以下是事件中的控制 HelloWorldSecene.cpp中的实现

    void HelloWorld::menuCallback(CCObject* pSender) {
        CCMenuItem *item = (CCMenuItem *)pSender;
        switch (item->getTag()) {
            case 1: // down start
                CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(HelloWorld::updateUI), this, 0, false); // HttpClient中參考
                isStop = false;
                this->threadStart();
                break;
            case 2: // down stop
                isStop = true;
                break;
            case 3:
                if (isStop) {
                    CCLog("downFilePath:%s",downFilePath.c_str());
                    if (access(downFilePath.c_str(), 0) == 0) {
                        remove(downFilePath.c_str());
                        CCMessageBox("删除成功", "温馨提示");
                    }else{
                        CCMessageBox("没有找到文件文件夹", "温馨提示");
                    }
                }else{
                    CCMessageBox("下载中或没有文件下载", "温馨提示");
                }
                
                break;
            default:
                break;
        }
    }

    3。

    实现线程类并回调设置

    // 启动线程的方法
    int HelloWorld::threadStart() {
        pthread_mutex_init(&g_downloadMutex, NULL);
        int errCode=0;
        pthread_t th_curlDown; // 线程初始化
        do {
            pthread_attr_t tAttr;
            errCode=pthread_attr_init(&tAttr);
            CC_BREAK_IF(errCode!=0);
            errCode=pthread_attr_setdetachstate(&tAttr, PTHREAD_CREATE_DETACHED);
            if(errCode!=0) {
                pthread_attr_destroy(&tAttr);
                break;
            }
            errCode=pthread_create(&th_curlDown, &tAttr, thread_funcation, this);
        } while (0);
        return errCode;
    }
    
    // 须要线程来完毕的功能都写在这个函数里
    void* HelloWorld::thread_funcation(void *arg) {
        CCLOG("thread started...");
        HelloWorld *hw = (HelloWorld*)arg;
        hw->ccc = new CurlDown("http://developer.baidu.com/map/static/doc/output/BaiduMap_AndroidSDK_v2.4.0_All.zip",hw->downFilePath);
        //    ccc->mDownloadUrl = "http://developer.baidu.com/map/static/doc/output/BaiduMap_AndroidSDK_v2.4.0_All.zip";
        //    int leng = ccc->getDownloadFileLenth();
        hw->ccc->setDelegate(hw);
        hw->ccc->downloadControler();
        
        return NULL;
    }

    4.实现回调进度、成功、错误(里面用到线程锁对数据进度更新UI,本来对线程就不熟悉,问了群里面的大牛,看了不少资料)

    void HelloWorld::onError(CurlDown::ErrorCode errorCode){
        CCLog("error");
        
        pthread_mutex_lock(&g_downloadMutex);
        updateStr = "error";
        pthread_mutex_unlock(&g_downloadMutex);
        
        CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(HelloWorld::updateUI), this);
    }
    void HelloWorld::onProgress(double percent, void *delegate, string filefullPath){ // 下载进度
        CCLog("donw progress:%.2f%%",percent);
        
        if (isStop) {
            CurlDown * cd = (CurlDown *)delegate;
            //        pthread_mutex_lock(&g_downloadMutex);
            cd->setStopDown();
            //        pthread_mutex_unlock(&g_downloadMutex);
        }
        
        pthread_mutex_lock(&g_downloadMutex);
        const char * per =CCString::createWithFormat("donw progress:%.2f%%",percent)->getCString();
        updateStr = per;
        downFilePath = filefullPath;
        pthread_mutex_unlock(&g_downloadMutex);
    }
    void HelloWorld::onSuccess(string filefullPath){
        CCLog("success");
        
        pthread_mutex_lock(&g_downloadMutex);
        updateStr = "success";
        downFilePath = filefullPath;
        pthread_mutex_unlock(&g_downloadMutex);
    }

    5.CurlDown.h CurlDown.cpp类实现 (能够直接抽取出来用于不论什么地方。没有牵涉到cocos2d-x部分,cocos2d-x 部分能够删除没关系)

    1)对类初始化

    static pthread_mutex_t g_downloadMutex_1;
    
    CurlDown::~CurlDown(){
        mFileLenth = 0;
    }
    CurlDown::CurlDown():isStop(false),mDownloadUrl(""),timeout(2){ // test timeout 2 seconds. if release timeout 20 seconds
        mFileLenth = 0;
        mFilePath = "";
        pthread_mutex_init(&g_downloadMutex_1, NULL);
    }
    CurlDown::CurlDown(string downUrl,string filePath):mFileLenth(0),isStop(false),mDownloadUrl(downUrl),timeout(2),mFilePath(filePath){  // test timeout 2 seconds. if release timeout 20 seconds
        mDownloadUrl = downUrl;
        pthread_mutex_init(&g_downloadMutex_1, NULL);
    }
    
    void CurlDown::setDelegate(CurlDownDelegate * delegate) {
        mDelegate = delegate;
    }

    2)控制下载方法

    void CurlDown::downloadControler() {
        CCLog("--1-");
        mFileLenth = getDownloadFileLenth(); // 获取远程文件大小
        if (mFileLenth <= 0) {
            cout << "download file fail..." << endl;
            mDelegate->onError(kNetwork);
            return;
        }
        vector<string> searchPaths = CCFileUtils::sharedFileUtils()->getSearchPaths();
        vector<string>::iterator iter = searchPaths.begin();
        searchPaths.insert(iter, mFilePath);
        CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
        
        CCLog("--2-mFileLenth:%f",mFileLenth);
    	mFileName = mDownloadUrl.substr(mDownloadUrl.rfind('/') + 1);
        CCLog("--3-");
        CCLog("mFileName:%s;",mFileName.c_str());
    //    mFilePath = CCFileUtils::sharedFileUtils()->getWritablePath();
    //    CCLog("--5-");
        mFilePath = mFilePath + mFileName;
        CCLog("mFilePath:%s",mFilePath.c_str());
        CCLog("--6-");
        bool ret = false;
        while (true){ // 循环下载 每30秒进行下载 避免断网情况
            ret = download(); //直接下载 进行阻塞线程
            CCLog("----stop---%s------",isStop?"true":"false");
            if (isStop) { // 假设进行停止 break
                CCLog("----stop---------");
                break;
            }
            if (ret ){ //下载完毕
                break;
            }
            sleep(0.5); //每次下载中间间隔0.5秒
        }
        
        if (ret) {
            CCLog("download ok");
            mDelegate->onSuccess(mFilePath);
        } else {
            CCLog("download fail");
            mDelegate->onError(kUncompress);
        }
    }

    3)核心下载

    #pragma mark 进行下载
    bool CurlDown::download() {
        FILE *fp = NULL;
        if(access(mFilePath.c_str(), 0)==0) { // 以二进制形式追加
            fp = fopen(mFilePath.c_str(), "ab+");
        } else { // 二进制写
            fp = fopen(mFilePath.c_str(), "wb");
        }
        
        if (fp == NULL) {// 假设文件初始化失败进行返回
            return false;
        }
        
        // 读取本地文件下载大小
        long localFileLenth = getLocalFileLength(); //已经下载的大小
        CCLog("filePath:%s。leng:%ld",mFilePath.c_str() , localFileLenth ); //4397779 //3377875
        
        CURL *handle = curl_easy_init();
        std::string packageUrl = mDownloadUrl; //下载地址+下载文件名称
        curl_easy_setopt(handle, CURLOPT_URL, packageUrl.c_str()); // http://curl.haxx.se/libcurl/c/fopen.html
        curl_easy_setopt(handle, CURLOPT_TIMEOUT, timeout);
        curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, my_write_func);   //写文件回调方法
        curl_easy_setopt(handle, CURLOPT_WRITEDATA, fp); // 写入文件对象
        curl_easy_setopt(handle, CURLOPT_RESUME_FROM, localFileLenth);  // 从本地大小位置进行请求数据
        //    curl_easy_setopt(handle, CURLOPT_RESUME_FROM_LARGE, localFileLenth); // 坑
        curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0L);
        curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, my_progress_func ); //下载进度回调方法
        curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, this); // 传入本类对象
        
        CURLcode res = curl_easy_perform(handle);
        fclose(fp);
        return res == CURLE_OK;
    }

    以下大家要问道的就是求源代码(^..^)源代码已经上传github https://github.com/pingchangxin/BPDownload cesd 下载位置:http://download.csdn.net/detail/vpingchangxin/7108649

    我就不再这里mac她跑到隔壁 windows在没有运行(至win繁琐的头痛的结构)

  • 相关阅读:
    Docker私有仓库
    Docker入门
    HBase表的数据导出和导入
    HBase shell的使用记录
    Redis集群模式(Cluster)部署
    Oracle数据库sqlldr工具的使用
    oracle使用impdp和expdp导入导出数据
    Linux自动同步时间的方法
    Linux配置ssh免密码登陆
    Linux中逻辑卷(LV)的创建、增大和减小
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4573005.html
Copyright © 2020-2023  润新知