`

在BREW中实现自己的GUI(8)-IWEB的封装

    博客分类:
  • brew
阅读更多

封装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;
                    }


http://images.csdn.net/syntaxhighlighting/OutliningI
分享到:
评论
3 楼 咖啡舞者 2009-05-05  
非常感谢这种分享精神.
2 楼 haorui215 2009-04-24  
[/size][size=zXlarge][align=center][/align]
1 楼 haorui215 2009-04-24  

相关推荐

Global site tag (gtag.js) - Google Analytics