- case ECmwapConn:
- {
- //对以前的数据进行清理
- iPrintBuf.SetLength(0) ;
- iFirstIn = ETrue ;
- if(iHttpDown) delete iHttpDown ;
-
- //new出下载引擎进行链接
- iHttpDown = CM5HttpDown::NewL(*this, HTTP_DOWN_CMWAP) ;
- iHttpDown->HttpConnPorxy(s8) ; //s8为网址
- iRecvSize = 0 ;
-
-
- // check whether the file exists
- User::LeaveIfError(iFs.Connect()) ;
- iRecvSize = 0 ;
- if(BaflUtils::FileExists(iFs, KTargetFilename)) {
- TInt seek_pos = 0 ;
- iFile.Open(iFs, KTargetFilename, EFileStream | EFileWrite) ;
- if(iFile.Size(iRecvSize) != KErrNone)
- iRecvSize = 0 ;
- //如果文件存在并且没有异常的话,打开文件并移到文件末尾,为追加模式
- iFile.Seek(ESeekEnd, seek_pos) ;
- } else {
- iFile.Replace(iFs, KTargetFilename, EFileStream | EFileWrite) ;
- }
- break ;
- }
-
-
- //下面来看CM5HttpDown引擎
- //那么这个是我们引擎给外界提供的观察者
- class M5HttpDownNotifier {
- public:
- virtual void M5PrintNotify(const TDesC & aMessage) = 0 ;
- virtual void M5RecvNotify(const TDesC8 & recv_buf) = 0 ;
- virtual void M5TimerExpireNotify() = 0 ;
- virtual void M5ErrorNotify(const TDesC& aErrMessage, TInt aErrCode = 0) = 0 ;
- };
- #endif
- class CM5HttpDown : public CBase, public MUINotifier {
-
- protected:
- // socket data
- TInt m_down_type ;
- CSocketsEngine * m_sock_eng ; //联网的socke引擎,此类肯定是比较重要的一部分
- TBool m_running ;
- TBool m_is_first_resp ;
- TInt m_web_port ;
- TInt m_total_bytes ;
- TInt m_recv_bytes;
- TBuf8<HTTP_SEND_BUF_LEN> m_send_buf ;
- TBuf8<HTTP_TEMP_BUF_LEN> m_web_addr ;
- TBuf8<HTTP_TEMP_BUF_LEN> m_web_fname ;
- M5HttpDownNotifier& m_m5_notifier ; //给外界提供的接口
-
- public: // MUINotifier implements
- void PrintNotify(const TDesC& aMessage, TUint aAttributes = 0) ;
- void RecvNotify(const TDesC8& aMessage) ;
- void ErrorNotify(const TDesC& aErrMessage, TInt aErrCode) ;
- void SetStatus(const TDesC& aStatus) ;
- protected: //自己使用的方法
- TInt Str2Int(const TDesC8 & s) ;
- TBool CheckRecv(const TDesC8& recv_buf) ;
- TBool ParseUri(TDesC8& uri, TDes8& web_addr, TDes8& web_fname, TInt& web_port) ;
- TBool ParseWebFileInfo(const TDesC8& recv_buf, TInt& total_length, TInt& jump_len) ;
- TBool GetRespField(const TDesC8& recv_buf, TDesC8& field_name, TDesC8& end_flag, TDes8& res) ;
-
- TBool InitSock(TDesC8& server_name, TInt server_port) ;
- TBool SendReq(TDesC8& req_str) ;
- TBool CloseSock() ;
- private:
- CM5HttpDown(M5HttpDownNotifier & m5_notifier) ;
- void ConstructL(TInt down_type) ;
- public: //引擎暴露给外界的借口如下,当然还有观察者的那些接口用以通知
- ~CM5HttpDown() ;
- static CM5HttpDown * NewL(M5HttpDownNotifier& m5_notifie, TInt down_type) ;
- static CM5HttpDown * NewLC(M5HttpDownNotifier& m5_notifier, TInt down_type) ;
- TBool IsRunning() {return m_running ; }
- TInt HttpTotalSize() { return m_total_bytes ; }
- TInt HttpRecvSize() { return m_recv_bytes ; }
- //其实主要就暴露了以下三个接口
- TBool HttpConnPorxy(TDesC8& uri) ;
- TBool HttpDown(TDesC8& uri, TInt recv_bytes = 0) ;
- TBool HttpStopDown() ;
- } ;
- #endif
- //下面来分析一下引擎暴露给我们接口
- TBool CM5HttpDown::HttpConnPorxy(TDesC8& uri)
- {
- m_running = true ;
-
- //解析我们传递进去的URL:地址 文件名称 端口号,当让HTTP是80
- ParseUri(uri, m_web_addr, m_web_fname, m_web_port) ;
-
- if(m_down_type == HTTP_DOWN_CMWAP) {
- TBuf8<20> proxy_svr ;
- proxy_svr.Copy(KCMCCWapProxy) ; //_LIT(KCMCCWapProxy, "10.0.0.172") ;
-
- //我们看到如果是wap链接,传递进去的是wap的代理地址,至于原理是什么,我们再慢慢分析
- if(!InitSock(proxy_svr, 80)) return EFalse ;
- } else {
- if(!InitSock(m_web_addr, m_web_port)) return EFalse ;
- }
- return ETrue ;
- }
- TBool CM5HttpDown::HttpDown(TDesC8& uri, TInt recv_bytes)
- {
- TBuf8<20> tmp_str ;
- m_recv_bytes = recv_bytes ;
- m_send_buf.SetLength(0) ;
-
- //此处主要是对是否已经有下载下来的内容进行分析
- if(m_recv_bytes == 0)
- {
-
- m_send_buf.Append(KHttpCommonGet1) ;
-
- //如果是wap链接,这个地方放的是uri,否则为文件名称
- //此处实际是用Socket组织了一个http的包,打算发送
- if(m_down_type == HTTP_DOWN_CMWAP)
- m_send_buf.Append(uri) ;
- else
- m_send_buf.Append(m_web_fname) ;
- m_send_buf.Append(KHttpCommonGet2) ;
- m_send_buf.Append(m_web_addr) ;
- m_send_buf.Append(KHttpCommonGet3) ;
- tmp_str.Format(_L8("%d"), m_web_port) ;
- m_send_buf.Append(tmp_str) ;
- m_send_buf.Append(KHttpCommonGet4) ;
-
- }
- else
- {
-
- m_send_buf.Append(KHttpResumeGet1) ;
- if(m_down_type == HTTP_DOWN_CMWAP)
- m_send_buf.Append(uri) ;
- else
- m_send_buf.Append(m_web_fname) ;
- m_send_buf.Append(KHttpResumeGet2) ;
- m_send_buf.Append(m_web_addr) ;
- m_send_buf.Append(KHttpResumeGet3) ;
- tmp_str.Format(_L8("%d"), m_web_port) ;
- m_send_buf.Append(tmp_str) ;
- //这里才是断点续传的要点,就是将已经下载的字节数传递到服务器(这个是HTTP协议本身来进行处理的)
- //不要想的有多神秘哦
- m_send_buf.Append(KHttpResumeGet4) ;
- tmp_str.Format(_L8("%d"), m_recv_bytes) ;
-
- m_send_buf.Append(tmp_str) ;
- m_send_buf.Append(KHttpResumeGet5) ;
-
- }
- // send the request
- //进行socke发送
- return SendReq(m_send_buf) ;
- }
- //关闭链接
- TBool CM5HttpDown::HttpStopDown()
- {
- return CloseSock() ;
- }
- //通过上面的观察,我们发现,我们现在需要弄明白
- //SendReq(m_send_buf) ;
- //InitSock(proxy_svr, 80)的实现,下面我们来看看,我也是学习,说的乱不要怪哦,呵呵
- TBool CM5HttpDown::InitSock(TDesC8& server_name, TInt server_port)
- {
- TBuf<50> svr_name ;
- svr_name.Copy(server_name) ;
- m_sock_eng->SetServerName(svr_name) ;
- m_sock_eng->SetPort(server_port) ;
- m_sock_eng->ConnectL() ;
- return ETrue ;
- }
- TBool CM5HttpDown::SendReq(TDesC8& req_str)
- {
- if(m_sock_eng->Connected()) {
- m_sock_eng->WriteL(req_str) ;
- return ETrue ;
- }
- return EFalse ;
- }
- //我们看到,其实上面的两个函数很简单,无非就是发送和链接,设置参数,主要功能是由
- //SocketEngine来实现的,我们去看看socketengine吧
- //这是对SocketEngine进行了一段截取
- #ifndef HTTP_DOWN_CMWAP
- #define HTTP_DOWN_CMWAP 0
- #define HTTP_DOWN_CMNET 1
- #endif
- class CSocketsEngine : public CActive, public MTimeOutNotifier, public MEngineNotifier
- {
- public: // new methods
-
- //这些是我们比较关心的接口
- void ConnectL();
- void Disconnect();
- void WriteL(const TDesC8& aData);
- void Read();
- //我们需要对以下接口也进行关注和注意
- TUint32 CreateCmnetIap() ;
- TUint32 CreateCmwapIap() ;
- void ConnectSmoothCMNET() ;
- void ConnectSmoothCMWAP() ;
- void ConnectL(TUint32 aAddr);
- }
- //下面我们对上面说需要注意的方法进行分析;
- void CSocketsEngine::ConnectL()
- {
- // Initiate connection process
- if (iEngineStatus == ENotConnected)
- {
- TInetAddr addr;
- if (addr.Input(iServerName) == KErrNone)
- {
- // server name is already a valid ip address
- ConnectL(addr.Address());
- }
- else // need to look up name using dns
- {
- //如果发现不合法,则需要去寻找IP地址,域名解析
- // Initiate DNS
- User::LeaveIfError(iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp));
- // DNS request for name resolution
- iResolver.GetByName(iServerName, iNameEntry, iStatus);
-
- //将引擎状态进行改变,方便RunL函数去进行处理
- ChangeStatus(ELookingUp);
- // Request time out
- iTimer->After(KTimeOut);
- SetActive();
- }
- }
- }
- void CSocketsEngine::WriteL(const TDesC8& aData)
- {
- // Write data to socket
- if (iEngineStatus == EConnected)
- {
- iSocketsWriter->IssueWriteL(aData);
- }
- }
-
- void CSocketsEngine::Read()
- {
- // Initiate read of data from socket
- if ((iEngineStatus == EConnected) && (!iSocketsReader->IsActive()))
- {
- iSocketsReader->Start();
- }
- }
- // from CActive
- void CSocketsEngine::RunL()
- {
- // Active object request complete handler.
- // iEngineStatus flags what request was made, so its
- // completion can be handled appropriately
- iTimer->Cancel(); // Cancel TimeOut timer before completion
- switch(iEngineStatus)
- {
- case EConnecting:
- // IP connection request
- if (iStatus == KErrNone)
- // Connection completed successfully
- {
- //如果链接成功,则开始监听读取
- ChangeStatus(EConnected);
- Read(); //Start CSocketsReader Active object
- }
- else
- {
- iSocket.Close();
- iConsole.ErrorNotify(KErrConnectionFailed, iStatus.Int());
- ChangeStatus(ENotConnected);
- }
- break;
- case ELookingUp:
- iResolver.Close();
- if (iStatus == KErrNone)
- {
- //域名解析成功则开始链接
- // DNS look up successful
- iNameRecord = iNameEntry();
- // Extract domain name and IP address from name record
- Print(KStrDomainName);
- Print(iNameRecord.iName);
- TBuf<15> ipAddr;
- TInetAddr::Cast(iNameRecord.iAddr).Output(ipAddr);
- Print(KStrIPAddr);
- Print(ipAddr);
- Print(KStrNewLine);
- // And connect to the IP address
- ChangeStatus(ENotConnected);
- ConnectL(TInetAddr::Cast(iNameRecord.iAddr).Address());
- }
- else
- {
- // DNS lookup failed
- iConsole.ErrorNotify(KErrDNSFailed, iStatus.Int());
- ChangeStatus(ENotConnected);
- }
- break;
- default:
- User::Panic(KPanicSocketsEngine, ESocketsBadStatus);
- break;
- };
- }
-
-
复制代码 |
-
总评分: 技术分 + 5
查看全部评分
|