標籤:
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繁瑣的頭痛的結構)
coco2dx c++ HTTP實現