IWEB的封装

封装IWeb其实并不算是GUI的范畴,但是一并说了罢。在BREW中实现网络访问有两个选择:ISocket和IWeb,我是比较倾向于使用IWeb 的,只要你不是要做一个长连接。因为服务端程序比较容易做,可以直接使用现成的WEB服务器,我们不再需要自己处理并发、缓存等网络服务必须要考虑的东西。

使用IWeb并非只能处理HTML的页面,事实上我们完全可以拿它来做文件下载、提交信息(如下载报告)之类的管理。也并非IWeb 只能与IHtmlViewer合并使用,我们完全可以将一个IMenuCtl的信息打成二进制包使用IWeb下载并用IMenuCtl来展示,也就是说把它当成一个ISocket一样来使用。

首先我们需要定义一个回调,用WSNotify定义了回调的通知参数,包括状态、代码以及获取的内容等等。

typedef  struct  _IWebSocket IWebSocket;

// 定义回调的参数
typedef  struct
{
    uint16  wStatus;
    
int         wCode;
    
byte      * pBuffer;
    uint32    bLength;
    uint32    cLength;

}
 WSNotify;

// 定义回调格式
typedef  void  ( * PFNWSOCKETNOTIFY)(
      
void   *             pvUser,
      WSNotify            aWSNotify
   );


再看看这个组件包括的成员变量有哪些吧,除了IWeb和IWebResp以外,还需要回调cbNotify、目标地址m_TargetURL、临时的内容缓冲区m_BodyBuffer等成员:

struct  _IWebSocket
{
    
const  AEEVTBL(IWebSocket)  *  pvt;

    uint32          m_nRefs;    
    IShell            
* m_pIShell;
    IModule            
* m_pIModule;

    AEECallback    cb; 

    PFNWSOCKETNOTIFY    cbNotify;
    
void                  * pUser;
    
    IWeb        
* m_pIWeb;    
    IWebResp    
* m_piWResp; 
    
    
// 保存下载文件内容的缓冲区
     byte          * m_BodyBuffer;    
    uint32        m_BodySize;    
    uint32        m_BodyAllocSize;

    
char          * m_LocationURL;

    
// 目标URL
     char          * m_TargetURL;
    
char          * m_Header;

    
// 当前状态
    uint8        m_State;

    
// 尝试次数
    uint8        tryCount;

    
byte         buf[ 1024 ];
    
byte         cBuffer[ 10240 ];
    
int             cLen;

}
;


要实现的接口函数是:

AEEINTERFACE(IWebSocket)
{
    DECLARE_IBASE(IWebSocket)    

    
byte *         ( * GetBuffer)            (IWebSocket  *  po,uint32  *  outSize);
    
void         ( * SetNotifyFn)            (IWebSocket  *  po,PFNWSOCKETNOTIFY cb, void   *  pUser);
    
void         ( * SetHeader)            (IWebSocket  *  po, const   char   *  header);
    
void         ( * SetURL)                (IWebSocket  *  po, const   char   *  url);
    
void         ( * Stop)                    (IWebSocket  *  po);
    
void         ( * Resume)                (IWebSocket  *  po);
    
void         ( * Start)                (IWebSocket  *  po);    
    
void         ( * StartStream)            (IWebSocket  *  po);
    
}
;


OK,实现就类似于BREW中的那个 IWeb例子,做两个Start函数,一个是普通的下载(每下一个包回调一次),另一个是流式(建立一个小的缓冲区,这个小缓冲满了则回调一次):

static   void  IWebSocket_Start(IWebSocket  * pMe)
{
    FREEIF(pMe
-> m_BodyBuffer);
    pMe
-> m_BodyBuffer  =  NULL;
    pMe
-> m_BodySize  =   0 ;
    pMe
-> m_BodyAllocSize  =   0 ;

    CALLBACK_Cancel(
& pMe -> cb);
    CALLBACK_Init(
& pMe -> cb, webDownloadData, pMe);
    
    
if ( ! pMe -> m_pIWeb)
        initWeb(pMe);

    IWEB_GetResponse(pMe
-> m_pIWeb,
                        (pMe
-> m_pIWeb,  & pMe -> m_piWResp,  & pMe -> cb, pMe -> m_TargetURL, 
                        WEBOPT_HANDLERDATA, pMe, 
                        WEBOPT_HEADERHANDLER, webHeader, 
                        WEBOPT_STATUSHANDLER, webStatus, 
                        WEBOPT_END));
  
}

static   void  IWebSocket_StartStream(IWebSocket  * pMe)
{
    FREEIF(pMe
-> m_BodyBuffer);
    pMe
-> m_BodyBuffer  =  NULL;
    pMe
-> m_BodySize  =   0 ;
    pMe
-> m_BodyAllocSize  =   0 ;

    pMe
-> cLen = 0 ;
    MEMSET(pMe
-> buf, 0 , sizeof (pMe -> buf));
    MEMSET(pMe
-> cBuffer, 0 , sizeof (pMe -> cBuffer));

    CALLBACK_Cancel(
& pMe -> cb);
    CALLBACK_Init(
& pMe -> cb, webDownloadStream, pMe);
    
    
if ( ! pMe -> m_pIWeb)
        initWeb(pMe);

    IWEB_GetResponse(pMe
-> m_pIWeb,
                        (pMe
-> m_pIWeb,  & pMe -> m_piWResp,  & pMe -> cb, pMe -> m_TargetURL, 
                        WEBOPT_HANDLERDATA, pMe, 
                        WEBOPT_HEADERHANDLER, webHeader, 
                        WEBOPT_STATUSHANDLER, webStatus, 
                        WEBOPT_END));
  
}


两个下载的具体实现是:

// 响应
static   void  webDownloadData( void   *  p)
{
    IWebSocket 
* pMe  =  (IWebSocket  * )p;
    
    WebRespInfo 
* pwri;
    
int  ByteCount;
           
    pwri 
=  IWEBRESP_GetInfo(pMe -> m_piWResp);

    
if ! WEB_ERROR_SUCCEEDED(pwri -> nCode) )
    
{
        FREEIF(pMe
-> m_BodyBuffer);
        pMe
-> m_BodyBuffer  =  NULL;
        pMe
-> m_BodySize  =   0 ;
        pMe
-> m_BodyAllocSize  =   0 ;

        
if ( (pwri -> nCode == 302   ||  pwri -> nCode == 301 &&  pMe -> m_LocationURL != NULL )
        
{
            pMe
-> tryCount = 0 ;

            FREEIF(pMe
-> m_TargetURL);
            pMe
-> m_TargetURL = NULL;
            pMe
-> m_TargetURL = STRDUP(pMe -> m_LocationURL);

            FREEIF(pMe
-> m_LocationURL);
            pMe
-> m_LocationURL = NULL;
            
            IWebSocket_Stop(pMe);
            ISHELL_SetTimer(pMe
-> m_pIShell, 0 ,(PFNNOTIFY)IWebSocket_Start,( void * )pMe);
            
return ;
        }


        
if (pMe -> tryCount < MAX_TRY_COUNT)
        
{
            IWebSocket_Stop(pMe);
            pMe
-> tryCount ++ ;
            ISHELL_SetTimer(pMe
-> m_pIShell, 3000 ,(PFNNOTIFY)IWebSocket_Start,( void * )pMe);
        }

        
else
        
{
            WSNotify wsn;
            wsn.wCode
= pwri -> nCode;
            wsn.wStatus
= WS_STATUS_ERROR;
            wsn.pBuffer
= NULL;
            wsn.bLength
= 0 ;
            wsn.cLength
= 0 ;
            pMe
-> cbNotify(pMe -> pUser,wsn);
        }

        
return ;
    }

    ISHELL_CancelTimer(pMe
-> m_pIShell,(PFNNOTIFY)IWebSocket_Start,( void * )pMe);

    MEMSET(pMe
-> buf, 0 , sizeof (pMe -> buf));       
    
if  ((ISource  * ) 0   !=  pwri -> pisMessage) 
    
{
        ISource 
*  pISource  =  pwri -> pisMessage;
        ByteCount 
=     ISOURCE_Read(pISource, ( char   * )pMe -> buf,  sizeof (pMe -> buf));
        
        
switch (ByteCount)
        
{
            
case  ISOURCE_END:     // 表示读网络完成                        
                 {
                    WSNotify wsn;

                    IWebSocket_Stop(pMe);
                    
                    wsn.wCode 
=   0 ;
                    wsn.wStatus 
=  WS_STATUS_SUCCESS;
                    wsn.pBuffer
= pMe -> m_BodyBuffer;
                    wsn.bLength
= pMe -> m_BodySize;
                    wsn.cLength
= pwri -> lContentLength;

                    pMe
-> cbNotify(pMe -> pUser,wsn);                
                    
break ;
                }

           
case  ISOURCE_ERROR:
                
{
                    WSNotify wsn;
                    wsn.wCode
= pwri -> nCode;
                    wsn.wStatus
= WS_STATUS_ERROR;
                    wsn.pBuffer
= NULL;
                    wsn.bLength
= 0 ;
                    wsn.cLength
= pwri -> lContentLength;

                    pMe
-> cbNotify(pMe -> pUser,wsn);
                }

                
break ;
           
case  ISOURCE_WAIT:               
                ISOURCE_Readable(pISource, 
& pMe -> cb);
                
break ;
           
default :               
               
if  (ByteCount)
               
{
                    
if  (pMe -> m_BodySize  +  ByteCount  >  pMe -> m_BodyAllocSize)
                    
{
                        
const   int  NewSize  =  pMe -> m_BodyAllocSize  +  ByteCount;
                        
byte *  NewBuf  =  ( byte * )REALLOC(pMe -> m_BodyBuffer, NewSize);
                       
                        
if  (NewBuf)
                        
{
                            pMe
-> m_BodyBuffer  =  NewBuf;
                            pMe
-> m_BodyAllocSize  =  NewSize;
                        }

                        
else
                            
return ;
                    }

                    
if (pMe -> m_BodySize  +  ByteCount  <=  pMe -> m_BodyAllocSize)
                    
{
                        MEMCPY(pMe
-> m_BodyBuffer  +  pMe -> m_BodySize, pMe -> buf, ByteCount);
                        pMe
-> m_BodySize  +=  ByteCount;
                    }


                    
// 每次下一个包,则回调一次
                     {
                        WSNotify wsn;
                        wsn.wCode 
=  pwri -> nCode;
                        wsn.wStatus 
=  WS_STATUS_TICK;
                        wsn.pBuffer
= pMe -> m_BodyBuffer;
                        wsn.bLength
= pMe -> m_BodySize;
                        wsn.cLength
= pwri -> lContentLength;

                        pMe
-> cbNotify(pMe -> pUser,wsn);    
                    }

               }

               
               ISOURCE_Readable(pISource, 
& pMe -> cb);
               
break ;
           }
 
       }
        
}


和流式:

// 流式响应
static   void  webDownloadStream( void   *  p)
{
    IWebSocket 
* pMe  =  (IWebSocket  * )p;
    
    WebRespInfo 
* pwri;
    
int  ByteCount;
           
    pwri 
=  IWEBRESP_GetInfo(pMe -> m_piWResp);

    
if ! WEB_ERROR_SUCCEEDED(pwri -> nCode) )
    
{
        FREEIF(pMe
-> m_BodyBuffer);
        pMe
-> m_BodyBuffer  =  NULL;
        pMe
-> m_BodySize  =   0 ;
        pMe
-> m_BodyAllocSize  =   0 ;

        
if ( (pwri -> nCode == 302   ||  pwri -> nCode == 301 &&  pMe -> m_LocationURL != NULL )
        
{
            pMe
-> tryCount = 0 ;

            FREEIF(pMe
-> m_TargetURL);
            pMe
-> m_TargetURL = NULL;
            pMe
-> m_TargetURL = STRDUP(pMe -> m_LocationURL);

            FREEIF(pMe
-> m_LocationURL);
            pMe
-> m_LocationURL = NULL;
            
            IWebSocket_Stop(pMe);
            ISHELL_SetTimer(pMe
-> m_pIShell, 0 ,(PFNNOTIFY)IWebSocket_StartStream,( void * )pMe);
            
return ;
        }


        
if (pMe -> tryCount < MAX_TRY_COUNT)
        
{
            IWebSocket_Stop(pMe);
            pMe
-> tryCount ++ ;
            ISHELL_SetTimer(pMe
-> m_pIShell, 3000 ,(PFNNOTIFY)IWebSocket_StartStream,( void * )pMe);
        }

        
else
        
{
            WSNotify wsn;
            wsn.wCode
= pwri -> nCode;
            wsn.wStatus
= WS_STATUS_ERROR;
            wsn.pBuffer
= NULL;
            wsn.cLength
= 0 ;
            wsn.bLength
= 0 ;
            pMe
-> cbNotify(pMe -> pUser,wsn);
        }

        
return ;
    }

    ISHELL_CancelTimer(pMe
-> m_pIShell,(PFNNOTIFY)IWebSocket_StartStream,( void * )pMe);
    
    MEMSET(pMe
-> buf,( byte ) ' ' , sizeof (pMe -> buf));       
    
if  ((ISource  * ) 0   !=  pwri -> pisMessage) 
    
{
        ISource 
*  pISource  =  pwri -> pisMessage;
        ByteCount 
=     ISOURCE_Read(pISource, ( char   * )pMe -> buf,  sizeof (pMe -> buf));
        
        
switch (ByteCount)
        
{
            
case  ISOURCE_END:     // 表示读网络完成                        
                 {
                    WSNotify wsn;

                    IWebSocket_Stop(pMe);

                    
// 先回调一次tick
                    wsn.wCode = pwri -> nCode;
                    wsn.wStatus
= WS_STATUS_TICK;
                    wsn.pBuffer
= pMe -> cBuffer;
                    wsn.bLength
= pMe -> cLen;
                    wsn.cLength
= pwri -> lContentLength;

                    pMe
-> cbNotify(pMe -> pUser,wsn);
                    
                    
// 再回调成功
                    
                    wsn.wCode 
=   0 ;
                    wsn.wStatus 
=  WS_STATUS_SUCCESS;
                    wsn.pBuffer
= NULL;
                    wsn.bLength
= 0 ;
                    wsn.cLength
= pwri -> lContentLength;

                    pMe
-> cbNotify(pMe -> pUser,wsn);
                
                    
break ;
                }

           
case  ISOURCE_ERROR:
                
{
                    WSNotify wsn;
                    wsn.wCode
= pwri -> nCode;
                    wsn.wStatus
= WS_STATUS_ERROR;
                    wsn.pBuffer
= NULL;
                    wsn.bLength
= 0 ;
                    wsn.cLength
= pwri -> lContentLength;

                    pMe
-> cbNotify(pMe -> pUser,wsn);
                }

                
break ;
           
case  ISOURCE_WAIT:               
                ISOURCE_Readable(pISource, 
& pMe -> cb);
                
break ;
           
default :               
               
if  (ByteCount)
               
{
                    
if (pMe -> cLen  +  ByteCount  <=   sizeof (pMe -> cBuffer))
                    
{
                        
// 如果可以先放入临时空间
                        MEMCPY(pMe -> cBuffer  +  pMe -> cLen, pMe -> buf, ByteCount);
                        pMe
-> cLen  +=  ByteCount;
                    }

                    
else
                    
{
                        
// 临时空间如果满了,则回调一次
                        WSNotify wsn;
                        wsn.wCode
= pwri -> nCode;
                        wsn.wStatus
= WS_STATUS_TICK;
                        wsn.pBuffer
= pMe -> cBuffer;
                        wsn.bLength
= pMe -> cLen;
                        wsn.cLength
= pwri -> lContentLength;

                        pMe
-> cbNotify(pMe -> pUser,wsn);

                        
// 然后将当前的内容再放入临时空间,从头开始了
                        MEMCPY(pMe -> cBuffer,pMe -> buf,ByteCount);
                        pMe
-> cLen = ByteCount;
                    }

                    
               }

               
               ISOURCE_Readable(pISource, 
& pMe -> cb);
               
break ;
           }
 
       }
    
}


OK。就是这样了,可以在回调中使用那个pBuffer,也可以在最后用GetBuffer取结果。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值