您现在的位置: 首页 > 网站导航收录 > 百科知识百科知识
stunk(stunk是什么意思)
文件,进度,下载器stunk(stunk是什么意思)
发布时间:2016-12-08加入收藏来源:互联网点击:
很多朋友想了解关于stunk的一些资料信息,下面是小编整理的与stunk相关的内容分享给大家,一起来看看吧。
游戏开发中需要动态下载资源。甚至支持热更新修复代码。都需要引擎支持文件下载功能。写个基于http协议的多线程文件下载器。用第三方库如何选择问题?如何实现接口方便调用问题?等等。其实前面也多次用到libcurl。libcurl作为是一个多协议的便于客户端使用的URL传输库。libcurl已经非常灵活。接口设计的非常细。完全可以满足需求。
这里分享一个基于libcurl的HTTP封装类,其功能包括:同步的(HTTP/HTTPS)GET、POST请求,以及文件下载和进度报告。通过网络通信1-5中通信相关的方式。游戏开发中用到的通信基本都囊括了。引擎底层已经具备了强大的通信能力和提供完善的接口。后续的重点就是如何使用好接口。和提高开发效率。尤其是团队中多人参与研发。如何高效协助的问题。必然需要完整的工具链实现网络消息生成。使真正开发者无需关注底层。只需依葫芦画瓢接收和发送消息即可。但作为游戏开发者还是需要多花些精力去实现下。知识大爆炸时代更需要组织代码能力强的人才。尽量减少代码编程的时间。
C++实现下载器类:Gk8HttpLoader.h
#ifndef __GK8HTTPLOADER_H__#define __GK8HTTPLOADER_H__#pragma once#include "Gk8BaseObj.h"#include "Gk8ByteMaker.h"#include "curl/curl.h"#define GK8LOADER_COUNT 0x0001#define GK8LOADER_SIZE 0x0002#define GK8LOADER_ONESIZE 0x0003class Gk8HttpLoader:public Gk8BaseObj{ DECLARE_TOSPP_MAP;private: GK8_BOOL m_bLoading; //是否正在文件下载 Gk8ByteMaker m_iFileBufData; //[文件BUFF数据] GK8_INT m_nLoadShowCase; //[下载显示模式:1个数进度,2整体大小进度,3单个大小进度] Gk8Var m_iLoadProgressCallVar; Gk8Var m_iLoadFinishCallVar; GK8_INT m_nLoadFileCount; //[已下载文件个数] GK8_INT m_nSumFileCount; //[总文件个数] GK8_INT m_nLoadFileSize; //[已下载文件大小] GK8_INT m_nSumFileSize; //[总文件大小]private: GK8_BOOL InitLoaderThreadSemphore();public: Gk8HttpLoader(); virtual ~Gk8HttpLoader(); static Gk8HttpLoader* GetInstance(); GK8_VOID Destroy(); GK8_VOID TOSPPFUNC AddLoaderFile(GK8_LPCSTR lpFileName,GK8_LPCSTR lpLoaderUrl,GK8_LPCSTR lpLocalFile,GK8_INT nFileSize); GK8_VOID TOSPPFUNC SetHttpLoad(GK8_INT nLoadShowCase,Gk8Var& iLoadProgressCallVar,Gk8Var& iLoadFinishCallVar); GK8_VOID TOSPPFUNC HttpLoaderFile(); ; GK8_VOID OnProgress(GK8_LPVOID lpLoaderData,GK8_CDOUBLE dlTotal,GK8_CDOUBLE dlNow); GK8_VOID ShowLoadBar(GK8_LPVOID lpLoaderData); GK8_VOID HttpLoaderTick();};#endifC++实现下载器类:Gk8HttpLoader.cpp
#include "Gk8HttpLoader.h"#include "Gk8OperSys.h"#include "Gk8SetMb.cpp"#include "Gk8BufEntry.cpp"#include "Gk8FileUtil.h"#include queue#include pthread.h#include semaphore.h#include errno.h#include fcntl.htypedef struct tagLOADERDATA{ GK8_UINT nNameId; //[文件名ID] GK8_LPCSTR pFileName; //[下载文件名] GK8_LPCSTR pLoaderUrl; //[下载HTTP URL] GK8_LPCSTR pLocalFile; //[本地文件存放地] GK8_INT nFileSize; //[文件大小] Gk8ByteMaker* pFileBufData; //[文件BUFF数据] GK8_BOOL bSucceed; //[HTTP下载请求反馈成功] GK8_INT nResponseCode; //[HTTP下载请求反馈码] Gk8Str sErrorBuffer; //[HTTP下载请求错误信息]}LOADERDATA,*LPLOADERDATA;static Gk8Str sg_iLoadProgressEvent("OnLoadProgress"); //[下载进度信息]static Gk8Str sg_iLoadFinishEvent("OnLoadFinish"); //[下载完成信息]static Gk8HttpLoader* sg_pHttpLoader=NULL; //[静态HTTP下载器]static Gk8BufEntryLOADERDATA,256* s_pLoaderCache=NULL;static GK8_BOOL sg_bHttpLoaderQuit=false; //[退出HTTP下载器]static sem_t* sg_pLoaderSem=NULL; //[信号量的数据类型]//[线程及互斥定义]static pthread_t sg_LoaderNetWorkThread; //[HTTP下载线程]static pthread_mutex_t sg_RequestLoaderMutex; //[HTTP请求下载互斥体]static pthread_mutex_t sg_ResponseLoaderMutex; //[HTTP响应下载互斥体]static Gk8SetMbLPLOADERDATA sg_iRequestLoaderQueue; //[HTTP下载请求队列]static Gk8SetMbLPLOADERDATA sg_iResponseLoaderQueue; //[HTTP下载响应队列]static GK8_CHAR sg_szLoaderErrorBuf[CURL_ERROR_SIZE]; //[错误信息]static Gk8Str sg_iLoaderErrorStr;typedef size_t (*HTTPLOADERWRITE_CALLBACK)(GK8_LPVOID lpData,size_t nSize,size_t nMemBlock,GK8_LPVOID lpResponseData);#if (GK8_TARGET_PLATFORM==GK8_PLATFORM_IOS)#define GK8_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 1#else#define GK8_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 0#endif#if GK8_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE#define GK8_ASYNC_HTTPREQUEST_SEMAPHORE "Gk8HttpAsync"#elsestatic sem_t sg_iLoaderSem;#endifGK8_INT ProcessLoaderTask(LPLOADERDATA pHttpLoaderResponse,HTTPLOADERWRITE_CALLBACK lpCallBack,GK8_LPINT lpResponseCode);//[接收HTTP下载数据]size_t WriteHttpLoaderData(GK8_LPVOID lpData,size_t nSize,size_t nMemBlock,GK8_LPVOID lpResponseData){ Gk8ByteMaker* pResponseData=(Gk8ByteMaker*)lpResponseData; size_t nLength=nSize*nMemBlock; pResponseData-WriteBuf(lpData,(GK8_INT)nLength); return nLength;}//[进度回调]size_t HandleLoaderProgress(GK8_LPVOID lpBuffer,GK8_DOUBLE dlTotal,GK8_DOUBLE dlNow,GK8_DOUBLE ulTotal,GK8_DOUBLE ulNow){ LPLOADERDATA pHttpLoaderResponse=(LPLOADERDATA)lpBuffer; Gk8HttpLoader* pHttpLoader=Gk8HttpLoader::GetInstance(); pHttpLoader-OnProgress(pHttpLoaderResponse,dlTotal,dlNow); return 0;}//[处理POST请求:流的行事发出]GK8_INT ProcessLoaderTask(LPLOADERDATA pHttpLoaderResponse,HTTPLOADERWRITE_CALLBACK lpWriteCallBack,GK8_LPINT lpResponseCode){ CURLcode nCurlCode=CURL_LAST; CURL* pCurl=curl_easy_init(); do { //远程URL,支持HTTP,HTTPS,FTP nCurlCode=curl_easy_setopt(pCurl,CURLOPT_URL,pHttpLoaderResponse-pLoaderUrl); if(nCurlCode!=CURLE_OK) break; //设置User-Agent Gk8Str iUserAgentStr="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1" nCurlCode=curl_easy_setopt(pCurl,CURLOPT_USERAGENT,iUserAgentStr); if(nCurlCode!=CURLE_OK) break; //设置重定向的最大次数 nCurlCode=curl_easy_setopt(pCurl,CURLOPT_MAXREDIRS,5); if(nCurlCode!=CURLE_OK) break; //设置301,302跳转跟随location nCurlCode=curl_easy_setopt(pCurl,CURLOPT_FOLLOWLOCATION,1); if(nCurlCode!=CURLE_OK) break; nCurlCode=curl_easy_setopt(pCurl,CURLOPT_NOSIGNAL,1L); if(nCurlCode!=CURLE_OK) break; nCurlCode=curl_easy_setopt(pCurl,CURLOPT_POST,false); if(nCurlCode!=CURLE_OK) break; //下载内容回调函数 nCurlCode=curl_easy_setopt(pCurl,CURLOPT_WRITEFUNCTION,lpWriteCallBack); if(nCurlCode!=CURLE_OK) break; nCurlCode=curl_easy_setopt(pCurl,CURLOPT_WRITEDATA,pHttpLoaderResponse-pFileBufData); if(nCurlCode!=CURLE_OK) break; //进度回调函数 nCurlCode=curl_easy_setopt(pCurl,CURLOPT_NOPROGRESS, 0); if(nCurlCode!=CURLE_OK) break; nCurlCode=curl_easy_setopt(pCurl,CURLOPT_PROGRESSDATA,pHttpLoaderResponse); if(nCurlCode!=CURLE_OK) break; nCurlCode=curl_easy_setopt(pCurl,CURLOPT_PROGRESSFUNCTION,HandleLoaderProgress); if(nCurlCode!=CURLE_OK) break; //跳过服务器SSL验证,不使用CA证书 nCurlCode=curl_easy_setopt(pCurl,CURLOPT_SSL_VERIFYPEER,0L); if(nCurlCode!=CURLE_OK) break; //验证服务器端发送的证书,默认是2(高),1(中),0(禁用) nCurlCode=curl_easy_setopt(pCurl,CURLOPT_SSL_VERIFYHOST,0L); if(nCurlCode!=CURLE_OK) break; nCurlCode=curl_easy_setopt(pCurl,CURLOPT_ERRORBUFFER,sg_szLoaderErrorBuf); if(nCurlCode!=CURLE_OK) return false; nCurlCode=curl_easy_perform(pCurl); if(nCurlCode!=CURLE_OK) break; nCurlCode=curl_easy_getinfo(pCurl,CURLINFO_RESPONSE_CODE,lpResponseCode); if(nCurlCode!=CURLE_OK||*lpResponseCode!=200) { nCurlCode=CURLE_HTTP_RETURNED_ERROR; } }while(0); if(pCurl) curl_easy_cleanup(pCurl); return (nCurlCode==CURLE_OK?0:1);}//[创建网络下载线程]static GK8_LPVOID LoaderNetWorkThread(GK8_LPVOID lpData){ LPLOADERDATA pHttpLoaderRequest=NULL; LPLOADERDATA pHttpLoaderResponse=NULL; while(true) { //Wait for http request tasks from main thread GK8_INT nSemWaitRet=sem_wait(sg_pLoaderSem); if(nSemWaitRet0) { _GK8ERR"HttpRequest async thread semaphore error:"strerror(errno)CR; break; } if(sg_bHttpLoaderQuit) break; //[第一步:发送HTTP请求] pHttpLoaderRequest=NULL; pthread_mutex_lock(&sg_RequestLoaderMutex); if(0!=sg_iRequestLoaderQueue.GetSize()) { pHttpLoaderRequest=sg_iRequestLoaderQueue.GetItemAt(0); sg_iRequestLoaderQueue.RemoveItemAt(0); } pthread_mutex_unlock(&sg_RequestLoaderMutex); if(NULL==pHttpLoaderRequest) continue; //[清除二进制数据] pHttpLoaderRequest-pFileBufData-ClearStream(); //[第二步:libCurl同步请求] //pHttpLoaderResponse=new LOADERDATA(); //memcpy(pHttpLoaderResponse,pHttpLoaderRequest,sizeof(LOADERDATA)); pHttpLoaderResponse=pHttpLoaderRequest; GK8_INT nResponseCode=-1; GK8_INT nRetValue=0; nRetValue=ProcessLoaderTask(pHttpLoaderResponse,WriteHttpLoaderData,&nResponseCode); pHttpLoaderResponse-nResponseCode=nResponseCode; if(nRetValue!=0) { pHttpLoaderResponse-bSucceed=false; sg_iLoaderErrorStr=sg_szLoaderErrorBuf; pHttpLoaderResponse-sErrorBuffer=sg_iLoaderErrorStr; }else { pHttpLoaderResponse-bSucceed=true; } pthread_mutex_lock(&sg_ResponseLoaderMutex); sg_iResponseLoaderQueue.AddItem(pHttpLoaderResponse); pthread_mutex_unlock(&sg_ResponseLoaderMutex); } pthread_mutex_lock(&sg_RequestLoaderMutex); sg_iRequestLoaderQueue.Clear(); pthread_mutex_unlock(&sg_RequestLoaderMutex); if(sg_pLoaderSem!=NULL) {#if GK8_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE sem_unlink(GK8_ASYNC_HTTPREQUEST_SEMAPHORE); sem_close(sg_pLoaderSem);#else sem_destroy(sg_pLoaderSem);#endif sg_pLoaderSem=NULL; pthread_mutex_destroy(&sg_RequestLoaderMutex); pthread_mutex_destroy(&sg_ResponseLoaderMutex); //[依次删除数据] GK8_INT nIndex; for(nIndex=0;nIndexsg_iRequestLoaderQueue.GetSize();nIndex++) { pHttpLoaderRequest=sg_iRequestLoaderQueue.GetItemAt(nIndex); delete pHttpLoaderRequest; } for(nIndex=0;nIndexsg_iResponseLoaderQueue.GetSize();nIndex++) { pHttpLoaderResponse=sg_iResponseLoaderQueue.GetItemAt(nIndex); delete pHttpLoaderResponse; } sg_iRequestLoaderQueue.Destroy(); sg_iResponseLoaderQueue.Destroy(); } pthread_exit(NULL); return 0;}/////////////////////////////////////////////CLASS-TOSPP////////////////////////////////////////////////////BEGIN_TOSPP_MAP(Gk8HttpLoader,Gk8BaseObj) TOSPP_FUNC(Gk8HttpLoader,AddLoaderFile,' ',"sssd","AddLoaderFile(lpFileName,lpLoaderUrl,lpLocalFile,nFileSize)") TOSPP_FUNC(Gk8HttpLoader,HttpLoaderFile,' ',"","HttpLoaderFile()") TOSPP_FUNC(Gk8HttpLoader,SetHttpLoad,' ',"d&v&v","SetHttpLoad(nLoadShowCase,iLoadProgressCallVar,iLoadFinishCallVar)")END_TOSPP_MAP()BEGIN_TOSPP_STATIC_FUN_MAP(Gk8HttpLoader) TOSPP_STATIC_FUNC(Gk8HttpLoader,GetInstance,'p',"","[Gk8HttpLoader* GetInstance()?创建对象]")END_TOSPP_STATIC_FUN_MAP/////////////////////////////////////////////////////////////////////////////////////////////////Gk8HttpLoader::Gk8HttpLoader(){ m_bLoading=false; m_nLoadShowCase=1; m_nLoadFileCount=0; m_nSumFileCount=0; m_nLoadFileSize=0; m_nSumFileSize=0; s_pLoaderCache=new Gk8BufEntryLOADERDATA,256;}Gk8HttpLoader::~Gk8HttpLoader(){ sg_bHttpLoaderQuit=true; if(sg_pLoaderSem!=NULL) { sem_post(sg_pLoaderSem); } Destroy();}//[初始化线程]GK8_BOOL Gk8HttpLoader::InitLoaderThreadSemphore(){ if(sg_pLoaderSem!=NULL) { return true; }else {#if GK8_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE sg_pLoaderSem=sem_open(GK8_ASYNC_HTTPREQUEST_SEMAPHORE,O_CREAT,0644,0); if(sg_pLoaderSem==SEM_FAILED) { _GK8ERR"Open HttpLoader Semaphore Failed"CR; sg_pLoaderSem=NULL; return false; }#else GK8_INT nSemRet=sem_init(&sg_iLoaderSem,0,0); if(nSemRet0) { _GK8ERR"Init HttpLoader Semaphore Failed"CR; return false; } sg_pLoaderSem=&sg_iLoaderSem;#endif pthread_mutex_init(&sg_RequestLoaderMutex,NULL); pthread_mutex_init(&sg_ResponseLoaderMutex,NULL); pthread_create(&sg_LoaderNetWorkThread,NULL,LoaderNetWorkThread,NULL); pthread_detach(sg_LoaderNetWorkThread); sg_bHttpLoaderQuit=false; } return true;}//[增加HTTP下载文件]GK8_VOID Gk8HttpLoader::AddLoaderFile(GK8_LPCSTR lpFileName,GK8_LPCSTR lpLoaderUrl,GK8_LPCSTR lpLocalFile,GK8_INT nFileSize){ GK8_UINT nNameId=Gk8OperSys::Str2UINT(lpFileName); LPLOADERDATA lpLoaderData=s_pLoaderCache-AddEntryWithNameId(nNameId); lpLoaderData-nNameId=nNameId; lpLoaderData-pFileName=lpFileName; lpLoaderData-pLoaderUrl=lpLoaderUrl; lpLoaderData-pLocalFile=lpLocalFile; lpLoaderData-nFileSize=nFileSize; lpLoaderData-pFileBufData=&m_iFileBufData; //[准备显示数据] m_nSumFileCount++; m_nSumFileSize+=nFileSize; m_iFileBufData.WriteAlloc(nFileSize);}GK8_VOID Gk8HttpLoader::SetHttpLoad(GK8_INT nLoadShowCase,Gk8Var& iLoadProgressCallVar,Gk8Var& iLoadFinishCallVar){ m_nLoadShowCase=nLoadShowCase; m_iLoadProgressCallVar=iLoadProgressCallVar; m_iLoadFinishCallVar=iLoadFinishCallVar; Gk8Var iEmptyVar; if(iLoadProgressCallVar.GetSize()==1 && iLoadProgressCallVar[0].IfInt()) SetEvent(sg_iLoadProgressEvent,iLoadProgressCallVar[0],iEmptyVar); if(iLoadFinishCallVar.GetSize()==1 && iLoadFinishCallVar[0].IfInt()) SetEvent(sg_iLoadFinishEvent,iLoadFinishCallVar[0],iEmptyVar);}//[开始HTTP下载文件]GK8_VOID Gk8HttpLoader::HttpLoaderFile(){ //正在下载中 if(m_bLoading) return; if(s_pLoaderCache-GetBufNum()1) { //[通知脚本下载完成] static Gk8Var sl_iParamVar; sl_iParamVar.RemoveAll(); if(m_iLoadFinishCallVar.GetSize()==1) { RunEventWithArgs(sg_iLoadFinishEvent,sl_iParamVar); }else { if(!m_iLoadFinishCallVar[0].IfPtr()||!IfObjPtr(m_iLoadFinishCallVar[0].GetPtr(),m_iLoadFinishCallVar[0].GetPtrId())) return; Gk8Obj* pBindObj=m_iLoadFinishCallVar[0].GetSafePtr(); pBindObj-OnCall(m_iLoadFinishCallVar[1],sl_iParamVar); } m_nLoadFileCount=0; m_nSumFileCount=0; m_nLoadFileSize=0; m_nSumFileSize=0; return; } LPLOADERDATA lpLoaderData=s_pLoaderCache-GetBufEntryAt(0); if(false==InitLoaderThreadSemphore()) return; if(!lpLoaderData) return; m_bLoading=true; pthread_mutex_lock(&sg_RequestLoaderMutex); sg_iRequestLoaderQueue.AddItem(lpLoaderData); pthread_mutex_unlock(&sg_RequestLoaderMutex); sem_post(sg_pLoaderSem);}//[处理进度条]GK8_VOID Gk8HttpLoader::OnProgress(GK8_LPVOID lpLoaderData,GK8_CDOUBLE dlTotal,GK8_CDOUBLE dlNow){ LPLOADERDATA pLoaderData=(LPLOADERDATA)lpLoaderData; static Gk8Var sl_iParamVar; sl_iParamVar.RemoveAll(); sl_iParamVarm_nLoadShowCasepLoaderData-pFileNamem_nLoadFileCountm_nSumFileCount (m_nLoadFileSize+(GK8_INT)dlNow)m_nSumFileSize(GK8_INT)dlTotal(GK8_INT)dlNow; if(m_iLoadProgressCallVar.GetSize()==1) { RunEventWithArgs(sg_iLoadProgressEvent,sl_iParamVar); }else { if(!m_iLoadProgressCallVar[0].IfPtr()||!IfObjPtr(m_iLoadProgressCallVar[0].GetPtr(),m_iLoadProgressCallVar[0].GetPtrId())) return; Gk8Obj* pBindObj=m_iLoadProgressCallVar[0].GetSafePtr(); pBindObj-OnCall(m_iLoadProgressCallVar[1],sl_iParamVar); }}//[显示进度条]GK8_VOID Gk8HttpLoader::ShowLoadBar(GK8_LPVOID lpLoaderData){ LPLOADERDATA pLoaderData=(LPLOADERDATA)lpLoaderData; GK8_DOUBLE dlTotal=pLoaderData-nFileSize; GK8_DOUBLE dlNow=pLoaderData-nFileSize; OnProgress(lpLoaderData,dlTotal,dlNow);}//[获取HTTP下载器单例]Gk8HttpLoader* Gk8HttpLoader::GetInstance(){ if(sg_pHttpLoader==NULL) sg_pHttpLoader=new Gk8HttpLoader(); return sg_pHttpLoader;}GK8_VOID Gk8HttpLoader::Destroy(){ if(s_pLoaderCache!=NULL) { delete s_pLoaderCache; s_pLoaderCache=NULL; }}//[HTTP下载器响应帧控制]GK8_VOID Gk8HttpLoader::HttpLoaderTick(){ if(sg_pLoaderSem==NULL) return; LPLOADERDATA pLoaderData=NULL; pthread_mutex_lock(&sg_ResponseLoaderMutex); if(sg_iResponseLoaderQueue.GetSize()0) { pLoaderData=sg_iResponseLoaderQueue.GetItemAt(0); sg_iResponseLoaderQueue.RemoveItemAt(0); } pthread_mutex_unlock(&sg_ResponseLoaderMutex); if(!pLoaderData) return; //[把服务器数据派遣到脚本中] Gk8Str iResponstStr; if(!pLoaderData-bSucceed) { _GK8ERR"Gk8HttpLoader Response Failed Error Is "pLoaderData-sErrorBuffer" nResponseCode:"pLoaderData-nResponseCodeCR; iResponstStr="UnKown Error" }else { //保存文件 Gk8File iFile; if(iFile.Open(pLoaderData-pLocalFile,Gk8File::modeWriteAbs)) { iFile.Write(pLoaderData-pFileBufData-GetBuf(),pLoaderData-pFileBufData-GetStreamSize()); iFile.Close(); } } m_nLoadFileCount++; ShowLoadBar(pLoaderData); m_nLoadFileSize+=pLoaderData-nFileSize; //移除已下载数据:继续下载 s_pLoaderCache-RemoveEntryWithNameId(pLoaderData-nNameId); m_bLoading=false; HttpLoaderFile();}上一篇:河蚌怎么做好吃 大河蚌怎么做好吃
下一篇:返回列表
相关链接 |
||
网友回复(共有 0 条回复) |