⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symbian 2nd支持cmnet和cmwap的断点续传的rsocket实现.htm

📁 一个symbian下的多线程下载程序和文档。
💻 HTM
📖 第 1 页 / 共 3 页
字号:
            <DIV>class CM5HttpDown : public CBase, public MUINotifier 
            {<BR>protected:<BR>&nbsp;&nbsp;&nbsp; // socket 
            data<BR>&nbsp;&nbsp;&nbsp; 
            TInt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            m_down_type ;&nbsp; // 下载的类型,是cmnet还是cmwap<BR>&nbsp;&nbsp;&nbsp; 
            CSocketsEngine *&nbsp;&nbsp; m_sock_eng ;&nbsp;&nbsp;&nbsp;// 
            常规的socket engine<BR>&nbsp;&nbsp;&nbsp; 
            TBool&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            m_running ;&nbsp;&nbsp;&nbsp; // 标志量用于标明下载是否开始<BR>&nbsp;&nbsp;&nbsp; 
            TBool&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            m_is_first_resp ; //&nbsp;由于移动对于cmwap有推送页面,这个标记就是用来</DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 
            检查第一次Get的结果是否为推送页面,hoho,</DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            // 如果是的话。。。屏蔽啦。。。<BR>&nbsp;&nbsp;&nbsp; 
            TInt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            m_web_port ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            //&nbsp;端口了,默认是80端口<BR>&nbsp;&nbsp;&nbsp; 
            TInt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            m_total_bytes ;&nbsp;&nbsp;&nbsp;// 
            这里就是保存数据包总共有多少字节<BR>&nbsp;&nbsp;&nbsp; 
            TInt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
            m_recv_bytes;&nbsp;&nbsp;&nbsp;&nbsp; // 这里保存了已经下载了多少字节,用于断点续传</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>// 
            下面是发送缓冲区定义以及一些地址字符串定义<BR>&nbsp;TBuf8&lt;HTTP_SEND_BUF_LEN&gt; 
            m_send_buf ; <BR>&nbsp;TBuf8&lt;HTTP_TEMP_BUF_LEN&gt; m_web_addr ; 
            <BR>&nbsp;TBuf8&lt;HTTP_TEMP_BUF_LEN&gt; m_web_fname ; </DIV>
            <DIV>&nbsp;M5HttpDownNotifier&amp;&nbsp;&nbsp; m_m5_notifier 
            ;&nbsp;&nbsp; // 用于给调用者回调,收到数据<BR>&nbsp;&nbsp;&nbsp; <BR>public: 
            //&nbsp;定义了ui notify的状态打印相关的函数<BR>&nbsp;void PrintNotify(const 
            TDesC&amp; aMessage, TUint aAttributes = 0) ;<BR>&nbsp;void 
            RecvNotify(const TDesC8&amp; aMessage) ;<BR>&nbsp;void 
            ErrorNotify(const TDesC&amp; aErrMessage, TInt aErrCode)&nbsp; ; 
            <BR>&nbsp;void SetStatus(const TDesC&amp; aStatus) ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>protected:</DIV>
            <DIV>&nbsp;// 把字符串转换成整数的函数<BR>&nbsp;TInt&nbsp; Str2Int(const TDesC8 
            &amp; s) ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;//&nbsp;检查收到的数据是移动的推送页面呢,还是正常的数据<BR>&nbsp;TBool 
            CheckRecv(const TDesC8&amp; recv_buf) ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 解析调用者传入的uri,便于把断点续传的头取出来,例如要下载的地址为:</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // <A 
            href="http://www.5mbox.com/bbs/mp1.mp3">www.5mbox.com/bbs/mp1.mp3</A>,那么就需要把这个uri分割为两部分:</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // <A 
            href="http://www.5mbox.com/">http://www.5mbox.com/</A>域名,用于往这台服务器上发送下载请求;/bbs/mp1.mp3文件名,用于构建</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 
            断点续传的请求包的包头,所以这个函数也很重要喔!!<BR>&nbsp;&nbsp;&nbsp; TBool 
            ParseUri(TDesC8&amp;&nbsp; uri, TDes8&amp; web_addr, TDes8&amp; 
            web_fname, TInt&amp; web_port) ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp;// 
            解析从服务器返回回来的结果,可以得到文件的大小,以及需要跳过的数据长度</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 
            PS:肯定是要把服务器返回的http头跳过去,给m5httpdownnotifier传入接收的数据了<BR>&nbsp;&nbsp;&nbsp; 
            TBool ParseWebFileInfo(const TDesC8&amp; recv_buf, TInt&amp; 
            total_length, TInt&amp; jump_len) ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 
            内部函数用于从http的头获取相应的字段<BR>&nbsp;&nbsp;&nbsp; TBool GetRespField(const 
            TDesC8&amp; recv_buf, TDesC8&amp; field_name, TDesC8&amp; end_flag, 
            TDes8&amp; res) ;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 
            下面这些就是常规的RSocket的操作了,初始化,发送请求,关闭连接<BR>&nbsp;&nbsp;&nbsp; TBool 
            InitSock(TDesC8&amp; server_name, TInt server_port) ; 
            <BR>&nbsp;&nbsp;&nbsp; TBool SendReq(TDesC8&amp; req_str) ; 
            <BR>&nbsp;&nbsp;&nbsp; TBool CloseSock() ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>private:<BR>&nbsp;CM5HttpDown(M5HttpDownNotifier &amp; 
            m5_notifier) ; <BR>&nbsp;void ConstructL() ; </DIV>
            <DIV>public:<BR>&nbsp;// symbian标准的二段式构造,无需多言。</DIV>
            <DIV>&nbsp;~CM5HttpDown() ; <BR>&nbsp;static CM5HttpDown * 
            NewL(M5HttpDownNotifier&amp; m5_notifier) ; <BR>&nbsp;static 
            CM5HttpDown * NewLC(M5HttpDownNotifier&amp; m5_notifier) ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 
            这两个是在下载过程中外部回调函数得到下载进度用的,例如文件的总的大小,现在已经下载的大小</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; TBool IsRunning() {return m_running ; 
            }<BR>&nbsp;&nbsp;&nbsp; TInt&nbsp; HttpTotalSize() { return 
            m_total_bytes ; }<BR>&nbsp;&nbsp;&nbsp; TInt&nbsp; HttpRecvSize() { 
            return m_recv_bytes ; } </DIV>
            <DIV>&nbsp;&nbsp;&nbsp; </DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 这里就是用来指定接入点的下载类型的了,是采用cmwap呢还是cmnet</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 正确的使用流程应该是先连接然后再下载</DIV>
            <DIV>&nbsp;TBool HttpConnPorxy(TDesC8&amp; uri, TInt down_type = 
            HTTP_DOWN_CMWAP) ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 这个函数就是开始下载了<BR>&nbsp;&nbsp;&nbsp; TBool 
            HttpDown(TDesC8&amp; uri, TInt recv_bytes = 0) ; <BR>&nbsp;TBool 
            HttpStopDown() ; <BR>} ; <BR>#endif</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>下面就是M5HttpDown.cpp的关键内容了:</DIV>
            <DIV>#include "m5httpdown.h"<BR>#include 
            &lt;e32std.h&gt;<BR>#include &lt;f32file.h&gt;</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>// 移动的代理网关ip地址定义</DIV>
            <DIV>_LIT(KCMCCWapProxy, "10.0.0.172") ;&nbsp; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>CM5HttpDown::CM5HttpDown(M5HttpDownNotifier &amp; 
            m5_notifier):</DIV>
            <DIV>m_m5_notifier(m5_notifier)<BR>{<BR>&nbsp;m_sock_eng = NULL ; 
            <BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>CM5HttpDown::~CM5HttpDown() 
            <BR>{<BR>&nbsp;if(m_sock_eng-&gt;IsActive()) 
            {<BR>&nbsp;&nbsp;m_sock_eng-&gt;Disconnect() ; 
            <BR>&nbsp;}<BR>&nbsp;delete m_sock_eng ; <BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>void CM5HttpDown::ConstructL()<BR>{<BR>&nbsp;m_running = EFalse 
            ;<BR>&nbsp;m_down_type = HTTP_DOWN_CMWAP ; <BR>&nbsp;m_is_first_resp 
            = ETrue ; <BR>&nbsp;m_total_bytes = 0 ; <BR>&nbsp;m_recv_bytes = 0 
            ;<BR>&nbsp;m_web_port = HTTP_WEB_PORT ; 
            <BR>&nbsp;m_web_addr.SetLength(0) ; 
            <BR>&nbsp;m_web_fname.SetLength(0) ;&nbsp; <BR>&nbsp;m_sock_eng = 
            CSocketsEngine::NewL(*this) ;<BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>CM5HttpDown * CM5HttpDown::NewL(M5HttpDownNotifier&amp; 
            m5_notifier)<BR>{<BR>&nbsp;CM5HttpDown * self = 
            CM5HttpDown::NewLC(m5_notifier);<BR>&nbsp;CleanupStack::Pop(self);<BR>&nbsp;return 
            self;<BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>CM5HttpDown * CM5HttpDown::NewLC(M5HttpDownNotifier&amp; 
            m5_notifier)<BR>{<BR>&nbsp;CM5HttpDown * self = new (ELeave) 
            CM5HttpDown(m5_notifier);<BR>&nbsp;CleanupStack::PushL(self);<BR>&nbsp;self-&gt;ConstructL();<BR>&nbsp;return 
            self;<BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>void CM5HttpDown::PrintNotify(const TDesC&amp; aMessage, TUint 
            aAttributes)<BR>{<BR>&nbsp;m_m5_notifier.M5PrintNotify(aMessage) ; 
            <BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>// 呵呵,这里通过检查在收到的数据中是否含有要下载的web地址来确定是否是移动的推送页面</DIV>
            <DIV>// 一般来说,移动的推送页面都有一个你的地址,再加上一个&amp;t=xxxxx这样的uri,所以可以</DIV>
            <DIV>// 利用这一点来做到判别是否是推送页面</DIV>
            <DIV>TBool CM5HttpDown::CheckRecv(const TDesC8&amp; 
            recv_buf)<BR>{<BR>&nbsp;TInt find_pos ; <BR>&nbsp;find_pos = 
            recv_buf.Find(m_web_addr) ; <BR>&nbsp;if(find_pos != KErrNotFound) 
            return EFalse ; </DIV>
            <DIV>&nbsp;return ETrue ; <BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>void CM5HttpDown::RecvNotify(const TDesC8&amp; 
            aMessage)<BR>{<BR>&nbsp;TInt recv_bytes = aMessage.Length() ; 
            <BR>&nbsp;TInt jump_length = 0 ; <BR>&nbsp;<BR>&nbsp;if(recv_bytes 
            &gt; 0) {</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp; // 
            如果是第一次收到的话,就需要判断是否是推送页面<BR>&nbsp;&nbsp;if(m_is_first_resp) 
            {<BR>&nbsp;&nbsp;&nbsp;if(CheckRecv(aMessage)) {<BR></DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp;// 如果不是推送页面,则把文件的总共大小读取出来</DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp;if(ParseWebFileInfo(aMessage, 
            m_total_bytes, jump_length)) {</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp; // 
            第一次接收数据,m_recv_bytes理论上应该等于0;如果不等于0则代表本次下载是</DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp; // 
            断点续传,需要把这个m_recv_bytes已经下载的字节数加入到m_total_bytes里面去。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(m_recv_bytes 
            &gt; 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_total_bytes += 
            m_recv_bytes ; </DIV>
            <DIV>&nbsp;</DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp; 
            //&nbsp;肯定了,实际收到的字节数是需要跳过http头的,所以这里引入了jump_length<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_recv_bytes 
            += (recv_bytes - jump_length) ; </DIV>
            <DIV>&nbsp;&nbsp;&nbsp; </DIV>
            <DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;一切准备妥当,然后调用M5RecvNotify函数来告知收到了数据<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_m5_notifier.M5RecvNotify(aMessage.Mid(jump_length)) 
            ; <BR>&nbsp;&nbsp;&nbsp;&nbsp;}</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; </DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 
            既然第一次已经收到数据了,接下来的数据就是源源不断的到来了,就不必每次都跟第一次接收到</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 数据还需要解析什么http这么麻烦了,直接收到,然后调用recv 
            notify即可。<BR>&nbsp;&nbsp;&nbsp;&nbsp;m_is_first_resp = false ; 
            <BR>&nbsp;&nbsp;&nbsp;} else {</DIV>
            <DIV>&nbsp;&nbsp;&nbsp; // 这里输出check 
            failed的时候,意味着收到了移动的推送页面,需要重发一遍下载的request才行<BR>&nbsp;&nbsp;&nbsp;&nbsp;TBuf&lt;20&gt; 
            s ; <BR>&nbsp;&nbsp;&nbsp;&nbsp;s.Format(_L("check failed !")) ; 
            <BR>&nbsp;&nbsp;&nbsp;&nbsp;PrintNotify(s) ; 
            <BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;} else 
            {<BR>&nbsp;&nbsp;&nbsp;// common receive procdure </DIV>
            <DIV>&nbsp;&nbsp; // 
            这里就是直接接收数据,然后存盘了<BR>&nbsp;&nbsp;&nbsp;if((m_recv_bytes + recv_bytes) 
            &gt; m_total_bytes) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;recv_bytes = 
            m_total_bytes - m_recv_bytes ; 
            <BR>&nbsp;&nbsp;&nbsp;&nbsp;m_recv_bytes = m_total_bytes ; 
            <BR>&nbsp;&nbsp;&nbsp;} else 
            {<BR>&nbsp;&nbsp;&nbsp;&nbsp;m_recv_bytes += recv_bytes 
            ;&nbsp;&nbsp;&nbsp; 
            <BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;m_m5_notifier.M5RecvNotify(aMessage) 
            ; <BR>&nbsp;&nbsp;}<BR>&nbsp;}<BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>void CM5HttpDown::ErrorNotify(const TDesC&amp; aErrMessage, 
            TInt aErrCode) 
            <BR>{<BR>&nbsp;m_m5_notifier.M5PrintNotify(aErrMessage) ; 
<BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>void CM5HttpDown::SetStatus(const TDesC&amp; 
            aStatus)<BR>{<BR>&nbsp;m_m5_notifier.M5PrintNotify(aStatus) ; 
            <BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>TBool CM5HttpDown::SendReq(TDesC8&amp; req_str) <BR>{<BR>&nbsp; 
            if(m_sock_eng-&gt;Connected()) {<BR>&nbsp;&nbsp;&nbsp; 
            m_sock_eng-&gt;WriteL(req_str) ; <BR>&nbsp;&nbsp;&nbsp; return ETrue 
            ; <BR>&nbsp; }<BR>&nbsp;&nbsp;&nbsp; return EFalse ; <BR>}</DIV>
            <DIV>&nbsp;</DIV>
            <DIV>// 这个函数看上去很让人恼火,没办法symbian的字符串描述符就是这个样子的。</DIV>
            <DIV>TBool CM5HttpDown::ParseUri(TDesC8&amp;&nbsp; uri, TDes8&amp; 
            web_addr, TDes8&amp; web_fname, TInt&amp; 
            web_port)<BR>{<BR>&nbsp;&nbsp;&nbsp; TPtrC8 uri_ptr ; 
            <BR>&nbsp;&nbsp;&nbsp; TBuf8&lt;30&gt; tmp_buf ; 
            <BR>&nbsp;&nbsp;&nbsp; TInt&nbsp; find_pos = 0 ; </DIV>
            <DIV>&nbsp;&nbsp;&nbsp; web_port = HTTP_WEB_PORT ; 
            <BR>&nbsp;&nbsp;&nbsp; if(uri.Length() &lt;= 0) return false ;</DIV>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -